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旧的备用节点。

相关推荐
zhu12893035562 分钟前
基于Rust与WebAssembly实现高性能前端计算
前端·rust·wasm
耶啵奶膘2 分钟前
uni-app:firstUI框架的选择器Select改造,添加一个搜索的插槽
前端·uni-app
旧识君7 分钟前
前端图片压缩实战:基于compressorjs的高效解决方案
前端·javascript·vue.js
爱上大树的小猪14 分钟前
【前端安全】模板字符串动态拼接HTML的防XSS完全指南
前端·安全·html
这里有鱼汤32 分钟前
你以为 Socket 只能做聊天室?揭秘 Python 网络编程的 8 种硬核用法
前端·后端·python
uhakadotcom34 分钟前
Wolfram.com:解锁计算技术和知识管理的强大工具
前端·面试·github
skyseey38 分钟前
笔记:Vue3+Vite 怎么导入静态资源,比如图片/组件
前端·javascript·笔记
清风细雨_林木木39 分钟前
Vue 中 this.$emit(“update:xx“,value) 和 :xx.sync 实现同步数据的做法
前端·javascript·vue.js
沐土Arvin1 小时前
Nginx 核心配置详解与性能优化最佳实践
运维·开发语言·前端·nginx·性能优化
恋猫de小郭1 小时前
Flutter Roadmap 2025 发布,快来看看有什么更新吧
android·前端·flutter