react的渲染过程
一、过程说明
React 的渲染流程可以分为三个阶段:
-
调和阶段(Reconciliation Phase)/ Diff 阶段
-
找出需要更新的部分,不直接操作 DOM;
-
是一个可以中断的过程(React 18 使用 Fiber 架构进行调度);
-
会生成一个更新的「虚拟 DOM 树」;
-
最终形成一个 Fiber 树。
-
-
提交阶段(Commit Phase)
-
将变化同步到 DOM;
-
不能被中断;
-
分为三个子阶段:
-
beforeMutation
:生命周期如getSnapshotBeforeUpdate
-
mutation
:执行 DOM 操作 -
layout
:生命周期如componentDidMount
,useLayoutEffect
-
-
-
浏览器渲染阶段
-
React 完成 DOM 更新后交给浏览器;
-
浏览器进行布局(layout)、绘制(paint)、合成(composite)等渲染工作
-
二、Fiber数据结构
{ tag: FunctionComponent, type: MyComponent, key: null, pendingProps: { foo: 'bar' }, memoizedProps: { foo: 'bar' }, memoizedState: {...}, alternate: currentFiber, // 指向旧 fiber flags: NoFlags, // 标记有没有变化(用于指导后面commit时候要不要更新dom) child: currentFiber.child, // 直接复用 }
三、事件循环及桢渲染
事件循环的步骤:
-
取出一个宏任务(macrotask)执行(如
setTimeout
、setImmediate
、MessageChannel
、postMessage
); -
宏任务执行完后,执行所有的微任务(microtasks,如
Promise.then
); -
然后如果到了下一帧的时间点,执行渲染(layout + paint)。 注意渲染都是浏览器等到每一桢开始,一并执行(如改变color等),便于性能提升;但是回流计算reflow(如改变offsetWidth等),则是立刻执行
-
// 浏览器不会马上 layout 和 paint div.style.width = '100px'; div.style.height = '100px'; // 会立刻触发 reflow const width = div.offsetWidth; const rect = div.getBoundingClientRect()
-
-
重复这个过程