React双缓存树渲染流程介绍

一、什么是React Fiber

我们都知道从React16.8开始引入了fiber架构。旧版的React的render过程是同步的,如果Render耗时较长,会阻塞页面的其他任务。新版本的Render过程拆分成多个异步任务(纤程),并且是可中断可恢复的,这就是React Fiber.

原理:Render过程主要工作是vdom diff算法找出两棵树的区别,本质上的树的遍历。在旧版本react,假设遍历发生了中断,虽然可以保留当下进行中节点的索引,下次继续时,我们的确可以继续遍历该节点下面的所有子节点,但是没有办法找到其父节点因为每个节点只有其子节点的指向。断点没有办法恢复,只能从头再来一遍。在新的fiber架构中,每个节点有三个指针:分别指向第一个子节点、下一个兄弟节点、父节点。这种数据结构就是fiberNode。

二、React双缓冲树

javascript 复制代码
import React from 'react';
import ReactDom from 'react-dom';

class Home extends React.Component {
  constructor(props) {
     super(props);
     this.state = { step: 0 };
     this.handleClick = this.handleClick.bind(this);
   }
   handleClick() {
     this.setState({step: this.state.step + 1})
    }
  render() {
     const { step } = this.state;
     return (
         <div id={step} onClick={this.handleClick}>
            {step}
         </div>
       )
     }
  }

ReactDom.render(<Home/>, document.getElementById('root'))

渲染流程

  • render阶段 构建workInProgress树,用于本次渲染
  • render结束,commit前 更新容器的finishedWork指针,通知页面渲染
  • commit结束 current树变成alternate树,workInProgress树变成current树,finishedWork树为空

第一次渲染

  • render阶段 初始化工作:创建容器和root fiberNode, current指针指向root fiber
  • 构建workInProgressi树,即将渲染到页面的vdom 除了child、sibling、return:指针,还有alternate它指向备用节点
  • render阶段结束,commit阶段开始 将fiber树容器的finishedWork指针执行workInProgress树root节点
  • commit阶段结束 current指向workInProgree树,finishedWork指向null

第二次渲染

  • render阶段 在current树的基础上构建workInProgress树,current.alternate节点不为空,存在备用节点,直接复用。

current树的其他子节点的alternate都为null,各自创建workInProgress节点

  • render阶段结束,commit阶段开始

    将fiber树容器的finishedWork指针指向workInProgress树root节点

  • commit阶段结束

    current指向workInProgress树,finishedWork指向null

第三次渲染

  • render阶段

    构建workInProgress树,所有fiber节点存在备用节点,直接复用,并将属性复制过去。

  • render阶段结束,commit阶段开始 将fiber树容器的finishedWork指针执行workInProgress树root节点
  • commit阶段结束

    current指向workInProgress树,finishedWork指向null

三、结论

通过上面三次渲染更新过程也可以看出,React在渲染时,会在current树和alternate树之间交替进行,倒来倒去。比如第四次渲染时,第二次渲染完成的alternate树又变成了current树,而第三次渲染完成的树又变成了alternate树。 那为什么React要复用备用的节点,而不是新创建一个呢?最大的原因是节省内存开销,通过复用引旧的备用节点,React不需要额外申请内存空间,在复用时可以直接将current fiber的属性复制到l旧的备用节点。

相关推荐
hunteritself2 分钟前
GPT Image2 + Seedance 2.0:3 小时从剧本到 AI 互动影游,深度实测复盘
前端·数据库·人工智能·深度学习·transformer
独秀不如众秀9 分钟前
前端页面引擎协议:由浅入深——从 30 行到 vform3 的演化之路
前端
学网安的肆伍18 分钟前
【044-WEB攻防篇】PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式
前端·sql·php
八号当铺35 分钟前
从 Prompt 到 AI 工程化:理解 Rules、Skills 与 Agent
前端·ai编程·cursor
didadida26239 分钟前
子路径部署 Vue/React 应用偶发白屏
前端·后端
invicinble40 分钟前
前端框架使用vue-cli (第五层:构建打包层--总体层介绍)
前端·vue.js·前端框架
前端那点事44 分钟前
Vuex刷新数据丢失?4种持久化方案全覆盖,从零到项目落地(实战完整版)
前端·vue.js
Cerrda44 分钟前
性能提升 satisfying!一个 Vue3 指令干掉页面上 200 个无用 Tooltip 实例
前端·设计
漫游的渔夫1 小时前
前端开发者做 AI Agent:别只渲染答案,用 7 个状态接住确认、错误和 trace
前端·人工智能·typescript
clove1 小时前
从 LLM 到 Agent:一篇文章课带你彻底搞懂 AI 智能体的核心逻辑
前端