EventPluginRegistry加载并获取事件插件模块如SimpleEventPlugin等,并约定此类插件构建合成事件对象event的顺序。
'use strict'; var _prodInvariant = require('./reactProdInvariant'); var invariant = require('fbjs/lib/invariant'); // 存储事件插件模块的执行顺序 var eventPluginOrder = null; // 以键值对存储加载的事件插件模块 var namesToPlugins = {}; // 对事件插件模块作校验,设定事件插件模块的执行顺序,完成注册(即publish) function recomputePluginOrdering() { if (!eventPluginOrder) { return; } for (var pluginName in namesToPlugins) { var pluginModule = namesToPlugins[pluginName]; // 通过injectEventPluginsByName方法加载事件插件模块没有在injectEventPluginOrder方法约定的事件插件执行顺序中,报错 var pluginIndex = eventPluginOrder.indexOf(pluginName); !(pluginIndex > -1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry:' + ' Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0; // 已加载并赋值给EventPluginRegistry.plugins的事件插件模块不予替换 if (EventPluginRegistry.plugins[pluginIndex]) { continue; } // 事件插件模块必须设定用于构建事件合成对象的extractEvents方法 !pluginModule.extractEvents ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry:' + ' Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0; EventPluginRegistry.plugins[pluginIndex] = pluginModule; // 事件插件模块支持的事件名集合,不同事件插件模块支持的事件名须互斥 var publishedEvents = pluginModule.eventTypes; for (var eventName in publishedEvents) { !publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry:' + ' Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0; } } } // 通过eventName获取事件插件模块pluginModule中的注册事件名,调用publishRegistrationName函数 // 向EventPluginRegistry.registrationNameModules、registrationNameDependencies、possibleRegistrationNames灌值 // 以SimpleEventPlugin中的onClick事件为例 // phasedRegistrationNames={bubbled:'onClick',captured:'onClickCapture'} // 最终调用publishRegistrationName("onClick",SimpleEventPlugin,"onClick") // 和publishRegistrationName("onClickCapture",SimpleEventPlugin,"onClick") function publishEventForPlugin(dispatchConfig, pluginModule, eventName) { // 两个事件插件模块拥有同名事件时,报错 !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginHub:' + ' More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0; EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig; var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; if (phasedRegistrationNames) { for (var phaseName in phasedRegistrationNames) { if (phasedRegistrationNames.hasOwnProperty(phaseName)) { var phasedRegistrationName = phasedRegistrationNames[phaseName]; publishRegistrationName(phasedRegistrationName, pluginModule, eventName); } } return true; } else if (dispatchConfig.registrationName) { publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName); return true; } return false; } // 完成注册,即向EventPluginRegistry.registrationNameModules模块赋值 // 供EventPluginHub模块快速通过事件名调用插件的extractEvents方法构建合成事件对象 function publishRegistrationName(registrationName, pluginModule, eventName) { // 同一个注册事件名不能被注册多次,也即不同事件插件模块的注册事件名互斥 !!EventPluginRegistry.registrationNameModules[registrationName] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginHub:' + ' More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0; // EventPluginRegistry.registrationNameModules添加{"onClick":SimpleEventPlugin} EventPluginRegistry.registrationNameModules[registrationName] = pluginModule; // EventPluginRegistry.registrationNameDependencies添加{"onClick":"topClick"} EventPluginRegistry.registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies; // EventPluginRegistry.possibleRegistrationNames添加{"onclick":"onClick"} if (process.env.NODE_ENV !== 'production') { var lowerCasedName = registrationName.toLowerCase(); EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName; if (registrationName === 'onDoubleClick') { EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName; } } } // 加载用于构建合成事件对象的事件插件模块,并提供通过注册事件名快速找到对应事件插件模块的属性 // 主要供EventPluginHub模块使用,也通过EventPluginHub模块完成事件插件模块的加载 var EventPluginRegistry = { // 顺序加载的事件插件模块 // 由injectEventPluginOrder方法设定调用事件插件模块的extractEvents方法构建合成事件对象的顺序 // injectEventPluginsByName方法通过名字加载具体的事件插件模块 // injectEventPluginOrder、injectEventPluginsByName暴露给EventPluginHub模块实现事件插件模块的加载 plugins: [], // { onClick:{ phasedRegistrationNames:{bubbled:'onClick',captured:'onClickCapture'}, dependencies:"topClick" } }形式 // 存储不同事件的冒泡注册事件名、捕获注册事件名,及依赖事件 eventNameDispatchConfigs: {}, // 以注册事件名为属性,事件插件模块作为值,供EventPluginHub模块快速通过事件名调用插件的extractEvents方法构建合成事件对象 // 与EventPluginRegistry.plugins属性的差别是,针对onClick事件,EventPluginRegistry.plugins只有onClick属性 // EventPluginRegistry.registrationNameModules有onClick、onClickCapture,对应冒泡和捕获事件 registrationNameModules: {}, // { onClick:"topClick" }形式 registrationNameDependencies: {}, // {onclick:"onClick",ondbclick:"onDoubleClick"}形式存储获取事件插件模块时可能使用的小写事件名 possibleRegistrationNames: process.env.NODE_ENV !== 'production' ? {} : null, // 在ReactDefaultInjection模块中,默认加载['ResponderEventPlugin','SimpleEventPlugin','TapEventPlugin', // 'EnterLeaveEventPlugin','ChangeEventPlugin','SelectEventPlugin','BeforeInputEventPlugin'] // 赋值给当前模块的eventPluginOrder缓存,最终影响EventPluginRegistry.plugins中事件插件模块的顺序 injectEventPluginOrder: function (injectedEventPluginOrder) { // eventPluginOrder只允许加载一次 !!eventPluginOrder ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry:' + ' Cannot inject event plugin ordering more than once.' + ' You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0; eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); recomputePluginOrdering(); }, // 以对象形式加载具体的事件插件模块 injectEventPluginsByName: function (injectedNamesToPlugins) { var isOrderingDirty = false; for (var pluginName in injectedNamesToPlugins) { if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { continue; } var pluginModule = injectedNamesToPlugins[pluginName]; if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) { // 同名称的事件插件模块不能加载两次 !!namesToPlugins[pluginName] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry:' + ' Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0; namesToPlugins[pluginName] = pluginModule; isOrderingDirty = true; } } if (isOrderingDirty) { recomputePluginOrdering(); } }, // 通过事件合成对象获取相应的事件插件模块 getPluginModuleForEvent: function (event) { var dispatchConfig = event.dispatchConfig; if (dispatchConfig.registrationName) { return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null; } if (dispatchConfig.phasedRegistrationNames !== undefined) { // pulling phasedRegistrationNames out of dispatchConfig helps Flow see // that it is not undefined. var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; for (var phase in phasedRegistrationNames) { if (!phasedRegistrationNames.hasOwnProperty(phase)) { continue; } var pluginModule = EventPluginRegistry.registrationNameModules[phasedRegistrationNames[phase]]; if (pluginModule) { return pluginModule; } } } return null; }, // 清空已注册的事件插件模块 _resetEventPlugins: function () { eventPluginOrder = null; for (var pluginName in namesToPlugins) { if (namesToPlugins.hasOwnProperty(pluginName)) { delete namesToPlugins[pluginName]; } } EventPluginRegistry.plugins.length = 0; var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs; for (var eventName in eventNameDispatchConfigs) { if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { delete eventNameDispatchConfigs[eventName]; } } var registrationNameModules = EventPluginRegistry.registrationNameModules; for (var registrationName in registrationNameModules) { if (registrationNameModules.hasOwnProperty(registrationName)) { delete registrationNameModules[registrationName]; } } if (process.env.NODE_ENV !== 'production') { var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames; for (var lowerCasedName in possibleRegistrationNames) { if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) { delete possibleRegistrationNames[lowerCasedName]; } } } } }; module.exports = EventPluginRegistry;