fix(core): should use native addEventListener in ngZone (#20672)

PR Close #20672
This commit is contained in:
JiaLi.Passion 2017-11-29 08:13:26 +09:00 committed by Miško Hevery
parent 0bef021321
commit 65a2cb8307
2 changed files with 41 additions and 26 deletions

View File

@ -154,37 +154,50 @@ export class DomEventsPlugin extends EventManagerPlugin {
let callback: EventListener = handler as EventListener; let callback: EventListener = handler as EventListener;
// if zonejs is loaded and current zone is not ngZone // if zonejs is loaded and current zone is not ngZone
// we keep Zone.current on target for later restoration. // we keep Zone.current on target for later restoration.
if (zoneJsLoaded && (!NgZone.isInAngularZone() || isBlackListedEvent(eventName))) { if (zoneJsLoaded) {
let symbolName = symbolNames[eventName]; if (!NgZone.isInAngularZone() || isBlackListedEvent(eventName)) {
if (!symbolName) { let symbolName = symbolNames[eventName];
symbolName = symbolNames[eventName] = __symbol__(ANGULAR + eventName + FALSE); if (!symbolName) {
} symbolName = symbolNames[eventName] = __symbol__(ANGULAR + eventName + FALSE);
let taskDatas: TaskData[] = (element as any)[symbolName]; }
const globalListenerRegistered = taskDatas && taskDatas.length > 0; let taskDatas: TaskData[] = (element as any)[symbolName];
if (!taskDatas) { const globalListenerRegistered = taskDatas && taskDatas.length > 0;
taskDatas = (element as any)[symbolName] = []; if (!taskDatas) {
} taskDatas = (element as any)[symbolName] = [];
}
const zone = isBlackListedEvent(eventName) ? Zone.root : Zone.current; const zone = isBlackListedEvent(eventName) ? Zone.root : Zone.current;
if (taskDatas.length === 0) { if (taskDatas.length === 0) {
taskDatas.push({zone: zone, handler: callback}); taskDatas.push({zone: zone, handler: callback});
} else { } else {
let callbackRegistered = false; let callbackRegistered = false;
for (let i = 0; i < taskDatas.length; i++) { for (let i = 0; i < taskDatas.length; i++) {
if (taskDatas[i].handler === callback) { if (taskDatas[i].handler === callback) {
callbackRegistered = true; callbackRegistered = true;
break; break;
}
}
if (!callbackRegistered) {
taskDatas.push({zone: zone, handler: callback});
} }
} }
if (!callbackRegistered) {
taskDatas.push({zone: zone, handler: callback});
}
}
if (!globalListenerRegistered) { if (!globalListenerRegistered) {
element[ADD_EVENT_LISTENER](eventName, globalListener, false); element[ADD_EVENT_LISTENER](eventName, globalListener, false);
}
} else {
// if zone.js loaded and we are in angular zone, we don't need to
// use zone.js patched addEventListener
const wrappedCallback = function() {
return self.ngZone.run(callback, this, arguments as any);
};
zoneJsLoaded.apply(element, [eventName, wrappedCallback, false]);
// we just use the underlying removeEventListener
return () => element[REMOVE_EVENT_LISTENER].apply(
element, [eventName, wrappedCallback, false]);
} }
} else { } else {
// use zone.js patched addEventListener or native addEventListener if zone.js not loaded
element[NATIVE_ADD_LISTENER](eventName, callback, false); element[NATIVE_ADD_LISTENER](eventName, callback, false);
} }
return () => this.removeEventListener(element, eventName, callback); return () => this.removeEventListener(element, eventName, callback);
@ -196,6 +209,8 @@ export class DomEventsPlugin extends EventManagerPlugin {
if (!underlyingRemove) { if (!underlyingRemove) {
return target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]); return target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]);
} }
// if zone.js loaded and wrappedCallback not exists, the callback was added in different zone
let symbolName = symbolNames[eventName]; let symbolName = symbolNames[eventName];
let taskDatas: TaskData[] = symbolName && target[symbolName]; let taskDatas: TaskData[] = symbolName && target[symbolName];
if (!taskDatas) { if (!taskDatas) {

View File

@ -283,7 +283,7 @@ export function main() {
}); });
getDOM().dispatchEvent(element, dispatchedEvent); getDOM().dispatchEvent(element, dispatchedEvent);
expect(receivedEvents).toEqual([dispatchedEvent, dispatchedEvent]); expect(receivedEvents).toEqual([dispatchedEvent, dispatchedEvent]);
expect(receivedZones).toEqual([Zone.root.name, 'fakeAngularZone']); expect(receivedZones).toEqual([Zone.root.name, 'angular']);
receivedEvents = []; receivedEvents = [];
remover1 && remover1(); remover1 && remover1();