1.初次渲染流程
流程:
- 根组件的
JSX定义会被babel转换为React.createElement的调用,其返回值为VNode树。 React.render调用,实例化FiberRootNode,并创建根Fiber节点HostRoot赋值给FiberRoot的current属性- 创建更新对象,其更新内容为
React.render接受到的第一个参数VNode树,将更新对象添加到HostRoot节点的updateQueue中 - 处理更新队列,从
HostRoot节点开始遍历,在其alternate属性中构建WIP树,在构建Fiber树的过程中会根据VNode的类型进行组件实例化、生命周期调用等工作,对需要操作视图的动作将其保存到Fiber节点的effectTag上面,将需要更新在DOM上的属性保存至updateQueue中,并将其与父节点的lastEffect连接。 - 当整颗树遍历完成后,进入
commit阶段,此阶段就是将effectList收集的DOM操作应用到屏幕上。 commit完成将current替换为WIP树。
2.更新渲染流程
图见上。
流程:
-
组件调用
setState触发更新,React通过this找到组件对应的Fiber对象,使用setState的参数创建更新对象,并将其添加进Fiber的更新队列中,然后开启调度流程。 -
从根
Fiber节点开始构建WIP树,此时会重点处理新旧节点的差异点,并尽可能复用旧的Fiber节点。 -
处理
Fiber节点,检查Fiber节点的更新队列是否有值,context是否有变化,如果没有则跳过。 -
处理更新队列,拿到最新的
state,调用shouldComponentUpdate判断是否需要更新。 -
调用
render方法获取VNode,进行diff算法,标记effectTag,收集到effectList中。- 对于新元素,标记插入
Placement - 旧
DOM元素,判断属性是否发生变化,标记Update - 对于删除的元素,标记删除
Deletion
- 对于新元素,标记插入
-
遍历处理
effectList,调用生命周期并更新DOM。
3.更新机制
众所周知,react的setState机制是“批量更新”和“异步执行”的。其中,“批量更新”是因,“异步执行”是果。
setState和 useState 只在合成事件和react生命周期(钩子函数)中是“异步”的,在原生事件和 setTimeout、Promise.resolve().then 中都是同步的。
1. react合成事件,如onClick等
2. react生命周期(钩子函数)包括componentDidMount、useEffect等等。
更新流程如下:
执行过程:
1.将setState传入的partialState参数存储在当前组件实例的state暂存队列中。
2.判断当前React是否处于批量更新状态,如果是,将当前组件加入待更新的组件队列中。
3.如果未处于批量更新状态,将批量更新状态标识设置为true,用事务再次调用前一步方法,保证当前组件加入到了待更新组件队列中。
4.调用事务的waper方法,遍历待更新组件队列依次执行更新。
5.执行生命周期componentWillReceiveProps。
6.将组件的state暂存队列中的state进行合并,获得最终要更新的state对象,并将队列置为空。
7.执行生命周期componentShouldUpdate,根据返回值判断是否要继续更新。
8.执行生命周期componentWillUpdate。
9.执行真正的更新,render。
10.执行生命周期componentDidUpdate。
参考文档: zhuanlan.zhihu.com/p/370183031 segmentfault.com/a/119000001… juejin.cn/post/684490…