React事件机制六--仿制事件流3

319 阅读2分钟

EventPluginHub.injection.getInstanceHandle().traverseTwoPhase方法

找到这个方法 ReactInstanceHandles 类。

    <!--
         EventPluginHub.injection.getInstanceHandle()方法返回一个InstanceHandle。而InstanceHandle 是调用 injectInstanceHandle方法注入进来的。
         ReactDefaultInjection类中注入的。
         注入的是 ReactInstanceHandles 类。
         
        所以EventPluginHub.injection.getInstanceHandle().traverseTwoPhase()方法实际是调用了ReactInstanceHandles类的下边方法:
        
         
    -->
    
    <!--
        targetID:就是触发事件的源元素的id。
        cb是一个方法 EventPropagators模块里的accumulateDirectionalDispatches方法。
        
    -->
    
    traverseTwoPhase: function (targetID, cb, arg) {
            if (targetID) {
              traverseParentPath('', targetID, cb, arg, true, false);
              traverseParentPath(targetID, '', cb, arg, false, true);
            }
    }
    

如上traverseTwoPhase方法是调用了如下方法:

关于traverseParentPath方法的源码分析

    traverseParentPath('', targetID, cb, arg, true, false);
    <!--
        这个方法会根据触发事件的元素的id,从根元素一直找到targetID。
        收集起来。把这一段的全部
        具体React是怎么做的
        找到一个id就调用一次EventPropagators模块里的accumulateDirectionalDispatches方法。
        看一下EventPropagators模块里的accumulateDirectionalDispatches方法
    -->
    
   function accumulateDirectionalDispatches(domID, upwards, event) {
        
        <!--
            根据domID找到存储在 listenerBank 中的侦听器
        -->
      var listener = listenerAtPhase(domID, event, phase);
        <!--
            把侦听器放入event的_dispatchListeners属性中。这个是取的了捕获阶段定义的事件。
            listenerBank中存储侦听器的方式是
            {
                onClick:{
                    .0:f(),
                    .0.1:f()
                }
            }
            每一种事件会将该类型的侦听器存储在一块。
            
        -->
        
      if (listener) {
        event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
        event._dispatchIDs = accumulateInto(event._dispatchIDs, domID);
      }
    }
    
    分割线
    ==============================================================
    traverseParentPath('', targetID, cb, arg, true, false);
    <!--
        这个方法与上边的方法相反,收集的是冒泡过程的事件侦听器。
    -->
    
    

经过上边的处理之后合成事件event中就存储了捕获阶段和冒泡阶段会触发的全部的侦听器。到此合成事件全部完成了。合成事件会被放在事件队列被执行。

ReactEventEmitterMixi模块的合成队列处理

    function runEventQueueInBatch(events) {
        <!--
            合成事件入队
        -->
        EventPluginHub.enqueueEvents(events);
        <!--
            合成事件队列执行
        -->
        EventPluginHub.processEventQueue(false);
    }

到此React的事件机制完成了。上边的代码只是挑出了核心代码来写,一些不重要的代码省略了,详细的代码参考github项目。传送门