Fiber架构工作原理

读者来稿 · admin与 batype 的 AI 分身对话整理

·1217 字 · 约 3 分钟

什么是“双缓存”?#

"双缓存"是一种常见的图形处理技术,用于在图像渲染中实现平滑的、无闪烁的更新效果。它通过使用两个缓冲区(即两块内存区域)来完成。其中一个缓冲区用于显示图像,而另一个缓冲区则用于在后台进行图像的更新和绘制。当更新完成后,通过交换两个缓冲区的引用,以实现无缝的切换和更新。

在图形处理中使用双缓存的好处包括:

  1. 无闪烁:通过在后台缓冲区进行绘制,然后将绘制结果一次性地切换到显示缓冲区,可以避免在图像更新过程中的闪烁问题。这对于实时图形、动画和视频等应用非常重要。
  2. 平滑更新:使用双缓冲可以实现平滑的更新效果。在后台缓冲区进行绘制和更新,然后在更新完成后将其切换到显示缓冲区,可以避免直接在显示缓冲区上进行绘制和修改,从而减少了可能出现的可见的渲染中间状态。
  3. 减少渲染延迟:使用双缓冲可以减少渲染延迟。由于绘制和更新发生在后台缓冲区,因此可以在绘制完成后立即切换到显示缓冲区,从而减少了等待绘制完成的时间,提高了渲染效率和响应时间。

双缓存技术在图形处理、动画、视频播放和游戏开发等领域得到广泛应用。在图形库、操作系统和桌面应用程序中,双缓存被用于实现平滑的图像渲染和交互效果。在前端开发中,双缓存也被广泛应用于图形绘制和动画效果的实现,以提供更好的用户体验。

React使用“双缓存”来完成Fiber树的构建与替换——对应着DOM树的创建与更新。

双缓存Fiber树#

React中最多会同时存在两棵Fiber树。当前屏幕上显示内容对应的Fiber树称为current Fiber树,正在内存中构建的Fiber树称为workInProgress Fiber树

current Fiber树中的Fiber节点被称为current fiberworkInProgress Fiber树中的Fiber节点被称为workInProgress fiber,他们通过alternate属性连接。

currentFiber.alternate === workInProgressFiber;
workInProgressFiber.alternate === currentFiber;

React 应用的根节点通过使 current 指针在不同 Fiber树rootFiber 间切换来完成 current Fiber 树指向的切换。

即当 workInProgress Fiber树 构建完成交给 Renderer 渲染在页面上后,应用根节点的 current 指针指向 workInProgress Fiber树 ,此时workInProgress Fiber树就变为current Fiber树

每次状态更新都会产生新的workInProgress Fiber树,通过currentworkInProgress的替换,完成DOM更新。

接下来我们以具体例子讲解mount时update时的构建/替换流程。

mount时#

考虑如下例子:

function App() {
  return (
    <h1>hello<span style={{ color: 'red' }}>world</span></h1>
  )
}

ReactDOM.render(<App/>, document.getElementById('root'));
  1. 首次执行ReactDOM.render会创建fiberRootNode(源码中叫fiberRoot)和rootFiber。其中fiberRootNode是整个应用的根节点,rootFiber<App/>所在组件树的根节点。

之所以要区分fiberRootNoderootFiber,是因为在应用中我们可以多次调用ReactDOM.render渲染不同的组件树,他们会拥有不同的rootFiber。但是整个应用的根节点只有一个,那就是fiberRootNode

fiberRootNodecurrent会指向当前页面上已渲染内容对应Fiber树,即current Fiber树

fiberRootNode

fiberRootNode.current = rootFiber;

由于是首屏渲染,页面中还没有挂载任何DOM,所以fiberRootNode.current指向的rootFiber没有任何子Fiber节点(即current Fiber树为空)。

  1. 接下来进入render阶段,根据组件返回的JSX在内存中依次创建Fiber节点并连接在一起构建Fiber树,被称为workInProgress Fiber树。(下图中右侧为内存中构建的树,左侧为页面显示的树)

在构建workInProgress Fiber树时会尝试复用current Fiber树中已有的Fiber节点内的属性,在首屏渲染时只有rootFiber存在对应的current fiber(即rootFiber.alternate)。

  1. 图中右侧已构建完的workInProgress Fiber树commit阶段渲染到页面。

此时DOM更新为右侧树对应的样子。fiberRootNodecurrent指针指向workInProgress Fiber树使其变为current Fiber 树

update时#

  1. 接下来我们点击p节点触发状态改变,这会开启一次新的render阶段并构建一棵新的workInProgress Fiber 树

mount时一样,workInProgress fiber的创建可以复用current Fiber树对应的节点数据。

  1. workInProgress Fiber 树render阶段完成构建后进入commit阶段渲染到页面上。渲染完毕后,workInProgress Fiber 树变为current Fiber 树

渲染过程