EventPluginRegistry

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;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值