事件的捕获冒泡
在ReactEvent处理的最后,对抽象事件对象的队列进行了集中处理,调用了EventPluginHub.processAbstractEventQueue方法,该方法为每一个抽象事件对象执行了executeDispatchesAndRelease方法。
通过执行getPluginModuleForAbstractEvent,可以找到负责处理该类型的插件,其实现如下:
function getPluginModuleForAbstractEvent(abstractEvent) {
if (abstractEvent.type.registrationName) {
return registrationNames[abstractEvent.type.registrationName];
} else {
for (var phase in abstractEvent.type.phasedRegistrationNames) {
if (!abstractEvent.type.phasedRegistrationNames.hasOwnProperty(phase)) {
continue;
}
var PluginModule = registrationNames[
abstractEvent.type.phasedRegistrationNames[phase]
];
if (PluginModule) {
return PluginModule;
}
}
}
return null;
}
registrationNames记录了每个不同类型的事件对应的插件(或者不同事件响应阶段的对应),因此,只要抽象事件对象的注册名称存在,就可以通过registrationName反查对应的pluginModule。而如果abtractEvent.type.registrationName不存在,则对比phasedRegistrationNames来查找相关的处理插件。
若找到的插件,且该插件定义了executeDispatch,则使用插件自定义的方法,否则的话,将调用EventPluginUtils中定义的默认executeDispatch方法,该方法就是执行了事件回调。
function executeDispatch(abstractEvent, listener, domID) {
listener(abstractEvent, domID);
}
至于自定义executeDispatch的情况,以SimpleEventPlugin为例,executeDispatch时,如果回调执行的返回值为false,就会阻止事件冒泡。
executeDispatch: function(abstractEvent, listener, domID) {
var returnValue = listener(abstractEvent, domID);
if (returnValue === false) {
abstractEvent.stopPropagation();
abstractEvent.preventDefault();
}
}
每一个AbstractEvent对象上,都保存了其事件回调函数,存放在_dispatchListeners中,里面的listener都是通过CallbackRegistery找到的与抽象事件对象及其响应阶段相对应的回调函数。
当抽象事件对象的回调处理完毕后(包括停止冒泡),React就会删除当前抽象事件对象上所有的回调函数信息,将抽象事件函数重新放回到缓冲池中。