连系源码完全明白 react事宜机制道理 03 - 事宜注册

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

媒介

这是 react 事宜机制的第三节 – 事宜注册,经由历程本文你将相识react 事宜的注册历程,以及在这个历程当中重要经由了哪些症结步骤,同时连系源码举行考证和加强邃晓。

文章触及到的源码是基于 react15.6.1版本,虽然不是最新版本然则也不会影响我们对 react 事宜机制的团体把握和邃晓。

文中不会说异常细节的内容,而是会把也许的流程和原理性的内容举行引见,做到对团体流程有个认知和邃晓。

内容纲要

  1. 重要做两件事 (事宜注册、事宜存储)
  2. 大抵流程
  3. 细致实行历程
  4. 总结

1. 重要做两件事

依据我的邃晓,react 事宜注册历程实在重要做了2件事:

a. 事宜注册

b. 事宜存储

a. 事宜注册 – 组件挂载阶段,依据组件内的声明的事宜范例-onclick,onchange 等,给 document 上增加事宜 -addEventListener,并指定一致的事宜处置惩罚顺序 dispatchEvent。

b. 事宜存储 – 就是把 react 组件内的一切事宜一致的存放到一个处所,也就是缓存起来,可以邃晓成放入一个对象内,为了在触发事宜的时刻可以查找到对应的要领去实行。

再配个图

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

2. 大抵流程

上面大抵说了事宜注册须要完成的两个目的,那完成目的的历程须要经由哪些症结处置惩罚呢?

起首 react 拿到将要挂载的组件的假造 dom(实在就是 react dom, 相似一个对象),然后处置惩罚react dom 的 props ,推断属性内是不是有声明为事宜的属性,比方onclick,这个时刻获得事宜范例 click 和对应的事宜处置惩罚顺序 fn,然后直行背面3步

a. 实行事宜注册

b. 将react dom ,事宜范例,处置惩罚函数 fn 放入数组存储

c. 组件挂载完成后,处置惩罚 b 步骤天生的数组,经由遍历把事宜处置惩罚函数存储到listenerBank中

再配个图

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

3.细致实行历程

3.1 得先从 jsx 提及

看个最熟习的代码,也是我们一样寻常的写法

handleFatherClick=()=>{

    }

    handleChildClick=()=>{

    }

    render(){
        return <div className="box">
                    <div className="father" onClick={this.handleFatherClick}>
                        <div className="child" onClick={this.handleChildClick}>child </div>
                    </div>
               </div>
    }

经由 babel 编译后,可以看到终究挪用的要领是react.createElement,而且声明的事宜范例和回调也是一个props。

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

react.createElement实行的效果会返回一个所谓的假造 dom(react element 或许 react dom),看下图

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

3. 2 最先处置惩罚props,拿到事宜范例和回调 fn

ReactDOMComponent在举行组件加载(mountComponent)、更新(updateComponent)的时刻,须要对props举行处置惩罚(_updateDOMProperties):

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》
可以看下 registrationNameModules 的内容,就不细说了。

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

3.3 注册事宜和事宜的存储

【注册事宜】

接着上面的代码实行到了这个要领

          enqueuePutListener(this, propKey, nextProp, transaction);

在这个要领里会举行事宜的注册以及事宜的存储,包含冒泡和捕捉的处置惩罚

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

依据当前的组件实例猎取猎取到最高父级-也就是document,然后实行要领 listenTo – 也是最症结的一个要领,举行事宜绑定处置惩罚

源码文件:ReactBrowerEventEmitter.js

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

末了实行EventListener.listen(冒泡)或许EventListener.capture(捕捉),

单看下冒泡的注册,实在就是addEventListener的第三个参数是 false

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

也可以看到注册事宜的时刻也对 ie 做了兼容。

上面没有看到 dispatchEvent 的定义,下面可以看到传入 dispatchEvent 要领的代码。

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

到这里事宜注册就完事儿了。

【事宜存储】

下一步最先事宜的存储,在 react 里一切事宜的触发都是经由历程 dispatchEvent要领一致举行派发的,而不是在注册的时刻直接注册声明的回调,来看下怎样存储的 。

【事宜存储结论】

react 把一切的事宜和事宜范例以及react 组件举行关联,把这个关联保存在了一个 map里,也就是一个对象里(键值对),然后在事宜触发的时刻去依据当前的组件id和事宜范例查找到对应的事宜。

再加个浅易图

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

看源码:

function enqueuePutListener(inst, registrationName, listener, transaction) {

  var containerInfo = inst._hostContainerInfo;
  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
  listenTo(registrationName, doc);//这个要领上面已说完


  //这里触及到了事件,事物会在今后的章节再引见,重要看事宜注册
  //下面的代码是将putListener放入数组,当组件挂载完后会顺次实行数组的回调。也就是putListener会顺次实行
  transaction.getReactMountReady().enqueue(putListener, {
    inst: inst,//组件实例
    registrationName: registrationName,//事宜范例 click
    listener: listener //事宜回调 fn
  });
}

function putListener() {
  var listenerToPut = this;
  //放入数组,回调行列
  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);
}

大抵的流程就是实行完listenTo(事宜注册),然后实行 putListener 要领举行事宜存储,一切的事宜都邑存储到一个对象中 – listenerBank,细致由EventPluginHub举行治理。

 //拿到组件唯一标识 id
    var getDictionaryKey = function getDictionaryKey(inst) {

      return '.' + inst._rootNodeID;

    }

   putListener: function putListener(inst, registrationName, listener) {

    //获得组件 id
        var key = getDictionaryKey(inst);

        //获得listenerBank对象中指定事宜范例的对象
        var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});

        //存储回调 fn
        bankForRegistrationName[key] = listener;

        //....
  }

listenerBank实在就是一个二级 map,如许的构造更轻易事宜的查找。

这里的组件 id 就是组件的唯一标识,然后和fn 举行关联,在触发阶段就可以找到相干的事宜回调。

看下listenerBank构造:

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

看到这个构造是不是是很熟习呢?就是我们寻常运用的 object.

到这里大抵的流程已说完,是不是是觉得有点邃晓又不大邃晓。

没紧要,再来个细致的图,从新邃晓下

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

4.末了

本文重如果从团体流程上引见了下 react 事宜中事宜的注册历程,并没有深切到源码的细节,有兴致的小伙儿可以自查下源码,也愿望本文可以带给你一些启示,若文章有表述不清或有题目的处所迎接留言交换。

更多精彩内容迎接关注我的民众号-前端张大胖

《连系源码完全明白 react事宜机制道理 03 - 事宜注册》

    原文作者:前端张大胖
    原文地址: https://segmentfault.com/a/1190000019387697
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞