React的注入机制

1,321 阅读3分钟

依赖注入

注入的核心作用是解耦。

#我们以React 0.13版本为例来看一下React的注入机制。

入口:ReactDOM类

    var ReactCurrentOwner = require('./ReactCurrentOwner');
    var ReactDOMTextComponent = require('./ReactDOMTextComponent');
    var ReactDefaultInjection = require('./ReactDefaultInjection');
    var ReactInstanceHandles = require('./ReactInstanceHandles');
    var ReactMount = require('./ReactMount');
    var ReactPerf = require('./ReactPerf');
    var ReactReconciler = require('./ReactReconciler');
    var ReactUpdates = require('./ReactUpdates');
    var ReactVersion = require('./ReactVersion');
    
    var findDOMNode = require('./findDOMNode');
    var renderSubtreeIntoContainer = require('./renderSubtreeIntoContainer');
    var warning = require('fbjs/lib/warning');
    
    ReactDefaultInjection.inject() -----------------(1)

ReactDOM类的(1)是核心。这一行代码主要做的事情就是调用了

ReactDefaultInjection 类的 Inject 方法。

这里我们就要转到ReactDefaultInjection类去了。先来看看ReactDefaultInjection类都有些什么。

ReactDefaultInjection类

首先,源码内容过多,这里就不全部贴出来,而是选择了其中的一项作为例子来说明。

var ReactInjection = require('./ReactInjection');

'引入了ReactInjection类,这个类是一个辅助类,
他的作用是导出一个React中所有需要注入依赖的类所提供的注入接口。
比如EventPluginHub这个类就需要一个依赖,名字叫做DefaultEventPluginOrder。
而EventPluginHub这个类提供了一个对外的接口injectEventPluginOrder,
用来注入自己需要的依赖(将自己需要的依赖DefaultEventPluginOrder当做参数传
递进来。这也是注入的实质。)。'

var DefaultEventPluginOrder = require('./DefaultEventPluginOrder');
'引入了DefaultEventPluginOrder类'

function inject() {
    ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder); -------------------(2)
}
    

ReactDefaultInjection类主要的就是引入各个类需要的依赖,而后调用各个类暴漏出来的注入方法(全都是inject开头的方法),来将需要的依赖注入到类中。

我们来看一下ReactInjection类中的内容

ReactInjection类

var DOMProperty = require('./DOMProperty');
var EventPluginHub = require('./EventPluginHub');
var ReactComponentEnvironment = require('./ReactComponentEnvironment');
var ReactClass = require('./ReactClass');
var ReactEmptyComponent = require('./ReactEmptyComponent');
var ReactBrowserEventEmitter = require('./ReactBrowserEventEmitter');
var ReactNativeComponent = require('./ReactNativeComponent');
var ReactPerf = require('./ReactPerf');
var ReactRootIndex = require('./ReactRootIndex');
var ReactUpdates = require('./ReactUpdates');

var ReactInjection = {
  Component: ReactComponentEnvironment.injection,
  Class: ReactClass.injection,
  DOMProperty: DOMProperty.injection,
  EmptyComponent: ReactEmptyComponent.injection,
  EventPluginHub: EventPluginHub.injection,-------------------(3)
  EventEmitter: ReactBrowserEventEmitter.injection,
  NativeComponent: ReactNativeComponent.injection,
  Perf: ReactPerf.injection,
  RootIndex: ReactRootIndex.injection,
  Updates: ReactUpdates.injection
};

module.exports = ReactInjection;

如上所示。ReactInjection类主要就是统一了一下都有那些地方需要注入内容。比如(3)就是我们上边例子说的EventPluginHub这个类就需要注入一些依赖。

接下来我们来看一下,需要依赖的类,比如EventPluginHub内部结构。

EventPluginHub类

var EventPluginHub = {
    '
        1 为了看起来清楚,我将多余的代码删除。
        2 多余的代码主要也是为了注入其他的内容
        3 该类提供了一个injection属性,injection属性是一个对象,期内包含
          了很多的注入方法。
        4 他被代码(3)引入了ReactInjection类中
        5 而后被代码(2)执行了,而后传递进来了DefaultEventPluginOrder类
        6 此处的injectEventPluginOrder方法,是在EventPluginRegistry类中写着。
        7 如此一来,EventPluginHub类需要用到的依赖DefaultEventPluginOrder
        类就被注入进来了。
    '
  /**
   * Methods for injecting dependencies.
   * 注入依赖的方法
   */
  injection: {
    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,
  },

最后我们看看注入进来的类DefaultEventPluginOrder,他是什么。

DefaultEventPluginOrder类

'
    说一下keyOf的作用,就是拿取出给定的对象内的每一项ke-value的key值。
    在取出key值之前要判断一下这key是否是给定的对象的自有属性。
'
var DefaultEventPluginOrder = [
    keyOf({ ResponderEventPlugin: null }), 
    keyOf({ SimpleEventPlugin: null }), 
    keyOf({ TapEventPlugin: null }), 
    keyOf({ EnterLeaveEventPlugin: null }), 
    keyOf({ ChangeEventPlugin: null }), 
    keyOf({ SelectEventPlugin: null }), 
    keyOf({ BeforeInputEventPlugin: null })
];

'
    最后说一下这个模块的作用:
    返回一个数组,这个数组内的每一项都是React的事件系统需要用到的事件插件
    他们必须要有一个顺序去载入,所以,在这里定义了一下。
'
module.exports = DefaultEventPluginOrder;

如上这些便是React的一次依赖注入的路线,凡是你发现以Inject开头的属性或者是方法,都是为了依赖注入这个机制。