fix(core): always remove DOM listeners and stream subscriptions
This is needed to prevent memory leaks. The DOM listeners don’t need to be removed for simple examples, but a big internal app shows memory leaks because of them. BREAKING CHANGE: - `Renderer.listen` now has to return a function that removes the event listener.
This commit is contained in:
@ -155,9 +155,9 @@ export class DomRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
listen(renderElement: any, name: string, callback: Function) {
|
||||
this._rootRenderer.eventManager.addEventListener(renderElement, name,
|
||||
decoratePreventDefault(callback));
|
||||
listen(renderElement: any, name: string, callback: Function): Function {
|
||||
return this._rootRenderer.eventManager.addEventListener(renderElement, name,
|
||||
decoratePreventDefault(callback));
|
||||
}
|
||||
|
||||
listenGlobal(target: string, name: string, callback: Function): Function {
|
||||
|
@ -8,10 +8,11 @@ export class DomEventsPlugin extends EventManagerPlugin {
|
||||
// events.
|
||||
supports(eventName: string): boolean { return true; }
|
||||
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function) {
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
var zone = this.manager.getZone();
|
||||
var outsideHandler = (event) => zone.run(() => handler(event));
|
||||
this.manager.getZone().runOutsideAngular(() => { DOM.on(element, eventName, outsideHandler); });
|
||||
return this.manager.getZone().runOutsideAngular(
|
||||
() => DOM.onAndCancel(element, eventName, outsideHandler));
|
||||
}
|
||||
|
||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
||||
@ -19,6 +20,6 @@ export class DomEventsPlugin extends EventManagerPlugin {
|
||||
var zone = this.manager.getZone();
|
||||
var outsideHandler = (event) => zone.run(() => handler(event));
|
||||
return this.manager.getZone().runOutsideAngular(
|
||||
() => { return DOM.onAndCancel(element, eventName, outsideHandler); });
|
||||
() => DOM.onAndCancel(element, eventName, outsideHandler));
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ export class EventManager {
|
||||
this._plugins = ListWrapper.reversed(plugins);
|
||||
}
|
||||
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function) {
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
var plugin = this._findPluginFor(eventName);
|
||||
plugin.addEventListener(element, eventName, handler);
|
||||
return plugin.addEventListener(element, eventName, handler);
|
||||
}
|
||||
|
||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
||||
@ -47,7 +47,7 @@ export class EventManagerPlugin {
|
||||
// That is equivalent to having supporting $event.target
|
||||
supports(eventName: string): boolean { return false; }
|
||||
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function) {
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
throw "not implemented";
|
||||
}
|
||||
|
||||
|
@ -15,17 +15,18 @@ export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
|
||||
return true;
|
||||
}
|
||||
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function) {
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
var zone = this.manager.getZone();
|
||||
eventName = eventName.toLowerCase();
|
||||
|
||||
zone.runOutsideAngular(function() {
|
||||
return zone.runOutsideAngular(function() {
|
||||
// Creating the manager bind events, must be done outside of angular
|
||||
var mc = new Hammer(element);
|
||||
mc.get('pinch').set({enable: true});
|
||||
mc.get('rotate').set({enable: true});
|
||||
|
||||
mc.on(eventName, function(eventObj) { zone.run(function() { handler(eventObj); }); });
|
||||
var handler = function(eventObj) { zone.run(function() { handler(eventObj); }); };
|
||||
mc.on(eventName, handler);
|
||||
return () => { mc.off(eventName, handler); };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -27,14 +27,15 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
||||
return isPresent(KeyEventsPlugin.parseEventName(eventName));
|
||||
}
|
||||
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function) {
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
var parsedEvent = KeyEventsPlugin.parseEventName(eventName);
|
||||
|
||||
var outsideHandler = KeyEventsPlugin.eventCallback(
|
||||
element, StringMapWrapper.get(parsedEvent, 'fullKey'), handler, this.manager.getZone());
|
||||
|
||||
this.manager.getZone().runOutsideAngular(() => {
|
||||
DOM.on(element, StringMapWrapper.get(parsedEvent, 'domEventName'), outsideHandler);
|
||||
return this.manager.getZone().runOutsideAngular(() => {
|
||||
return DOM.onAndCancel(element, StringMapWrapper.get(parsedEvent, 'domEventName'),
|
||||
outsideHandler);
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user