react 的执行过程

282 阅读3分钟

流程总览

react的执行过程可大致分为渲染提交两个阶段。渲染:生成fiberNode树和真实的dom树;提交:将dom树插入根节点dom里,执行生命周期或副作用。

渲染

从根节点开始,生成fiberNode树和真实的dom树,用workInProgressRoot指向新生成的成fiberNode树的根节点,用workInProgress指向当前正在处理的fiberNode,用fiberNode的stateNode指向该虚拟dom对应的真实dom。渲染过程:

  1. 设置循环的起点:生成过程为从根节点开始,利用fiberRootNode的信息(fiberNode)生成fiberNode,并用workInProgress指向该fiberNode,
  2. 循环遍历:设置好起点后,就可以循环遍历处理整个jsx树了,循环的流动方向为:从上往下,从左到右,再从最右返回上一层,循环到某个节点时就处理该节点:a,先处理完子节点:生成子节点对应的fiberNode树和dom树;b,再处理当前节点:生成对应的dom,并将所有直接子节点对应的dom插入当前节点dom上,将dom和fiberNode互相关联起来,以便必要时用(比如事件处理的时候要从dom上读取fiberNode,然后再从fiberNode上读取对应的函数)。所以fiberNode树的大致生成过程是 a,从上往下:先生成父节点,再生成子节点, b从左往右,先生成左边,再生成右边;dom树则是从左下角往上,再往右,本层生成完成后再回到上一层。

问题一:fiberNode是怎么生成的?用父节点属性上的element(根节点的element是在render函数里调用React.createElement方法生成的,并挂载到)

提交

完成渲染阶段后,就进入提交阶段了,主要逻辑在commitRootImpl函数里,

  1. 先清空调用堆积的副作用(调用flushPassiveEffects,主要是调用unmount和mounted相关的生命周期或副作用函数);
  2. 自底向上地执行类组件生命周期函数getSnapshotBeforeUpdate,最后清空根节点的dom内容,为后续插入内容做准备;
  3. 处理真实dom的增删改。自上往下地处理,先删掉要删除的子节点;再处理子节点上的删除、插入、更新;最后处理当前节点上的更新(函数组件调用Unmount和Mount函数);
  4. 处理虚拟dom的增删改和对应的生命周期函数或副作用函数(create、destroy)。该逻辑在flushPassiveEffectsImpl里实现,主要是调用commitPassiveUnmountEffects和commitPassiveMountEffects,两个函数都是从根节点开始遍历。
    commitPassiveUnmountEffects
    commitPassiveUnmountEffects的移动方向大致是向下 -> 向右 -> 向上。大致处理逻辑:a,执行当前fiberNode上要 删除的子节点(cur) 上的destroy方法;b,向下遍历处理要删除的节点,处理完子节点后,回到 cur 这个fiberNode,从fiberNode树上删除 cur 这个fiberNode;c,向右或向上移动。
    commitPassiveMountEffects
    commitPassiveMountEffects总体是从fiberNode树的左边有副作用的节点开始执行create方法,然后移动到右边(兄弟节点),再向上。a,向下遍历到子节点没有修改的节点;b,遍历执行当前fiberNode上的create方法;c,向右、向上回返执行fiberNode上的create方法