美文网首页
React 中的双缓冲机制

React 中的双缓冲机制

作者: 弱冠而不立 | 来源:发表于2021-01-27 10:15 被阅读0次

参考文章:React技术揭秘——什么是双缓冲

什么是双缓冲?

以 canvas 为例子,当我们用canvas绘制动画,每一帧绘制前都会调用ctx.clearRect清除上一帧的画面。
如果当前帧画面计算量比较大,我们就很容易因为绘制太慢了出现白屏。
为了解决这个问题,我们可以先在内存中绘制当前帧的动画,绘制完毕后,直接用当前帧替换上一帧,这样就省去了两帧的替换时间,不会出现从白屏到出现画面的闪烁情况。
这种在内存中构建并直接替换的技术叫做双缓冲
React使用“双缓存”来完成Fiber树的构建与替换——对应着DOM树的创建与更新。

React 哪里使用了这个技术?

render阶段开始于performSyncWorkOnRootperformConcurrentWorkOnRoot方法的调用。这取决于本次更新是同步更新还是异步更新。

未使用 Concurrent,同步更新 使用 Concurrent模式,进行异步更新

这两个方法的主要区别如下,但是它们都依赖于 workInProgress

// performSyncWorkOnRoot会调用该方法
function workLoopSync() {
  while (workInProgress !== null) {
    performUnitOfWork(workInProgress);
  }
}

// performConcurrentWorkOnRoot会调用该方法
function workLoopConcurrent() {
  while (workInProgress !== null && !shouldYield()) {
    performUnitOfWork(workInProgress);
  }
}

源码中,workInworkInProgress 是通过 createWorkInworkInProgress 创建的,createWorkInworkInProgress 主要逻辑如下:

// 这里入参中的 current 传入的是现有树结构中的 rootFiber 对象
function createWorkInProgress(current, pendingProps) {
  var workInProgress = current.alternate;
  // ReactDOM.render 触发的首屏渲染将进入这个逻辑
  if (workInProgress === null) {
    // 这是需要你关注的第一个点,workInProgress 是 createFiber 方法的返回值
    workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode);
    workInProgress.elementType = current.elementType;
    workInProgress.type = current.type;
    workInProgress.stateNode = current.stateNode;
    // 这是需要你关注的第二个点,workInProgress 的 alternate 将指向 current
    workInProgress.alternate = current;
    // 这是需要你关注的第三个点,current 的 alternate 将反过来指向 workInProgress
    current.alternate = workInProgress;
  } else {
    // else 的逻辑此处先不用关注
  }

  // 以下省略大量 workInProgress 对象的属性处理逻辑
  // 返回 workInProgress 节点
  return workInProgress;
}

重点如下:

  • createWorkInProgress 将调用 createFiber,workInProgress是 createFiber 方法的返回值(createFiber 返回的就是一个 FiberNode)
  • workInProgress 的 alternate 将指向 current
  • current 的 alternate 将反过来指向 workInProgress

其中还需要重点注意到的一行代码是:

workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode);

workInProgress 节点其实就是 current 节点(即 rootFiber)的副本。
再结合 current 指向 rootFiber 对象(同样是 FiberNode 实例),以及 current 和 workInProgress 通过 alternate(中文含义为备份) 互相连接这些信息,我们可以分析出这波操作执行完之后,整棵树的结构应该如下图所示:

举例说明

考虑如下例子:

function App() {
  const [num, add] = useState(0);
  return (
    <p onClick={() => add(num + 1)}>{num}</p>
  )
}

ReactDOM.render(<App/>, document.getElementById('root'));
mount 时
  1. 由于是首屏渲染,页面中还没有挂载任何DOM,所以fiberRootNode.current指向的rootFiber没有任何子Fiber节点(即current Fiber树为空)。
此时 currnent 尚未关联 workInProgress,也就是说内存中备用的 workInProgress Fiber 树尚未存在,还是 mount阶段
  1. 接下来进入render阶段,根据组件返回的JSX在内存中依次创建Fiber节点并连接在一起构建Fiber树,被称为workInProgress Fiber树。(下图中右侧为内存中构建的树,左侧为页面显示的树)

强调:在构建workInProgress Fiber树时会尝试复用current Fiber树中已有的Fiber节点内的属性,在首屏渲染时只有rootFiber存在对应的current fiber(即rootFiber.alternate)
这一点在下面的Update时,表现地更加明显。

  1. 将已构建完的workInProgress Fiber树在commit阶段渲染到页面。
    此时DOM更新为右侧树对应的样子。fiberRootNode的current指针指向workInProgress Fiber树使其变为current Fiber 树。
update 时
  1. 接下来我们点击p节点触发状态改变,这会开启一次新的render阶段并构建一棵新的workInProgress Fiber 树。
    在构建workInProgress Fiber树时会尝试复用current Fiber树中已有的Fiber节点内的属性

这个决定是否复用的过程就是Diffing算法,有关Diffing算法可以看这里

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

总结:

React 根据双缓冲的机制维护了两棵树:

  • 一棵是 Fiber 树用于渲染页面;
  • 一棵是 WorkInProgress Fiber 树,用于在内存中构建,然后方便在构建完成时直接替换用于渲染页面的 Fiber 树。

相关文章

  • React 中的双缓冲机制

    参考文章:React技术揭秘——什么是双缓冲[https://react.iamkasong.com/proces...

  • 双缓冲机制

    双缓冲一般来说适合多线程结合使用的 简单举个例子: 一个和尚要把水池注满水,现在他用一个水桶接水,水桶接满水后,他...

  • SurfaceView和TextureView

    SurfaceView SurfaceView中采用了双缓冲机制,保证了UI界面的流畅性,同时 SurfaceVi...

  • Android View双缓冲机制

    java的绘图时,都接触过图像的双缓存技术,解决绘制频繁导致闪屏的问题。今天,记录一下安卓客户端自定义View的缓...

  • 项目难点

    1.surfaceView问题 1.surfaceView 双缓冲机制,导致背景闪烁 (清空canva...

  • HDFS 架构师 1 —NameNode启动流程1

    0、NameNode 承受高流量的机制 双缓冲写入editlog 1、 NameNode流程启动剖析 ) 0...

  • 在Activity和附贴的Fragment中同时使用多Surfa

    SurfaceView因为独特的双缓冲机制,在android应用中十分普遍,视频播放器、摄像机预览等都会用到,如果...

  • iOS卡顿优化

    在iOS中是双缓冲机制(有前帧缓存、后帧缓存),配合垂直同步时钟(VSync信号)刷新屏幕的。按照60FPS的刷帧...

  • iOS性能优化 - 卡顿优化

    成像过程: 在iOS中是双缓冲机制,有前帧缓存、后帧缓存 成像原理: 发出垂直同步信号,告诉屏幕即将显示一帧数据;...

  • 缓冲机制

    1.几张图片看清缓冲机制 2.NSURLCache的7种常见用法 3.NSURLRequest的7种缓冲机制 4....

网友评论

      本文标题:React 中的双缓冲机制

      本文链接:https://www.haomeiwen.com/subject/ggngzktx.html