react中,current Fiber树,workInProgress Fiber树,虚拟dom,这三者是怎么样的关联关系?

这是个很核心的问题,让我画一张图来说清楚三者的关系。下面把三者关系说清楚:

image.png


虚拟 DOM(React Element)

JSX 经 Babel 编译成 React.createElement(...) 调用,返回的就是虚拟 DOM —— 一个普通 JS 对象 { type, props, key, ref }。它只描述”应该渲染什么” ,非常轻量,每次 render 都会重新生成。它本身不持有真实 DOM 引用、不知道副作用、不知道调度优先级。


Fiber 节点和 Fiber 树

Fiber 节点是虚拟 DOM 的”升级版”,除了描述信息外,还额外存储了:

  • 对应的真实 DOM 引用(stateNode)
  • 副作用标记(flags)
  • 调度优先级(lanes)
  • 钩子链表(memoizedState)
  • 指向父/子/兄弟节点的指针

谁创建了 Fiber 节点? 在 reconciler 的 render phase,React 以虚拟 DOM 为输入,调用 createFiber 或 createWorkInProgress 创建 Fiber 节点,组装成树。


current 树 vs workInProgress 树

这是 React 的双缓冲机制:

  • current 树:对应屏幕上当前显示的状态,FiberRoot.current 指向它的根节点
  • workInProgress(wip)树:本次更新正在构建的”草稿”,render phase 全程操作它
  • 两棵树中对应的节点通过 .alternate 属性互相引用

关键时序:

  1. 触发更新 → render phase 开始,以虚拟 DOM 为输入,基于 current 树创建/复用节点,构建 wip 树
  2. wip 树构建完成,进入 commit phase
  3. commit phase 结束 → FiberRoot.current = wip,完成指针交换
  4. 原来的 current 树此刻变成”空闲”状态,下次更新时作为 wip 复用的节点池

这样的好处是:render phase 可以被中断(操作的是 wip,不影响屏幕),commit phase 一气呵成(不可中断,直接操作真实 DOM),用户看到的始终是完整一致的 current 树。

资料来源:www.duskjoy.com