React-fiber架构解析

什么是fiber

React中虚拟dom是对真实dom的一种简化,但是一些真实dom能做的事情,虚拟dom做不了,于是就有了fiber,fiber其实是指一种数据结构,有很多的属性,它可以用一个纯的JS对象来表示,借由fiber上的属性做到一些虚拟dom功能上的拓展

//简化的fiber对象
const fiber={tag,//fiber类型key,type,//标签类型stateNode, //当前fiber实例child,     //子节点subling,   //兄弟节点return,    //父节点index,memoizedState,//当前fiber的statememoizedProps//当前fiber的propspendingProps,//传进来的新的propseffectTag,//当前节点要进行何等更新  placement新插入 update更新 deletion删除 placementAndUpdate插入加更新 noWork当前节点没有任何工作firstEffect,//当前有更新的第一个子节点lastEffect,//当前节点有更新的最后一个子节点nextEffect,//下一个要跟更新的子节点alternate,//连接current和workInProgress树updateQueue,//一条链表挂载的是当前fiber的新的状态//....其他属性
}

一、fiber架构

以往版本不足:

界面DOM节点多,渲染比较耗时

React为了弥补之前版本的一些不足,设计了一些新的算法,由新算法设计出现了fiber这种数据结构

fiber数据结构+新的算法=fiber架构

JSX:React语法糖 描述UI界面

1.1、react应用从始至中管理这基本的三样东西

1、Root-- (应用根 一个对象 存在一个属性指向current树,一个属性指向workInProgress树 )

2、current树 (保存上一次状态的fiber树 ,且每个fiber节点都对应这一个jsx节点)

3、workInProgress树(保存每次新的状态的fiber树,并且每个fiber节点都对应一个jsx节点)

1.2、react初次渲染

1、react在第一次开始创建root时, 就会同时创建uninitialFiber对象 (未初始化的fiber)、

使react的current指向了uninitialFiber对象 假设为上一次状态

2、之后再去创建本次要用到的workInProgress树

二、Fiber 的主要工作流程:

  1. ReactDOM.render() 引导 React 启动或调用 setState() 的时候开始创建或更新 Fiber 树。
  2. 从根节点开始遍历 Fiber Node Tree, 并且构建 WokeInProgress Tree(reconciliation 阶段)。
    • 本阶段可以暂停、终止、和重启,会导致 react 相关生命周期重复执行。
    • React 会生成两棵树,一棵是代表当前状态的 current tree,一棵是待更新的 workInProgress tree。
    • 遍历 current tree,重用或更新 Fiber Node 到 workInProgress tree,workInProgress tree 完成后会替换 current tree。
    • 每更新一个节点,同时生成该节点对应的 Effect List。
    • 为每个节点创建更新任务。
  3. 将创建的更新任务加入任务队列,等待调度。
    • 调度由 scheduler 模块完成,其核心职责是执行回调。
    • scheduler 模块实现了跨平台兼容的 requestIdleCallback。
    • 每处理完一个 Fiber Node 的更新,可以中断、挂起,或恢复。
  4. 根据 Effect List 更新 DOM (commit 阶段)。
    • React 会遍历 Effect List 将所有变更一次性更新到 DOM 上。
    • 这一阶段的工作会导致用户可见的变化。因此该过程不可中断,必须一直执行直到更新完成。

三、React16版本之前的渲染方式

1、模拟render渲染

//作用:将元素渲染到界面
//参数:element 元素,rootPatent 渲染元素的根节点let element =(<div id="1">I M hero<div>哈哈哈</div></div>
)function render(element,rootParent){//1.创建元素 let dom=docment.createElement(element.type)//2.给元素添加属性Object.keys(element.props).filter(prop=>prop!="children").forEach(v=>dom[v]=element.props[v])//3.将元素的子元素进行渲染(递归)if(Array.isArray(element.props.children)){element.props.children.forEach(c=>render(c,dom))}else{dom.innerHTML=element.props.children;}
}

2、element 元素Balbel编译后的数据结构 ,传入render()供react渲染

{"type": "div","key": null,"ref": null,"props": {"id": "1","children": ["I M hero", {"type": "div","key": null,"ref": null,"props": {"children": "哈哈哈"},"_owner": null,"_store": {}}]},"_owner": null,"_store": {}
}

3、 引发问题

因为如果界面节点多,层次深,递归渲染比较耗时

且 js是单线程的,UI线程和JS线程互斥,会照成界面卡顿,

所以 react在新版本中引入了 fiber的架构模式

4、老的架构方式造成界面掉帧卡顿原因

JS执行js引擎和页面渲染在同一个线程中,GUI渲染和JS执行两者是互斥的,如果某个js任务执行时间过长,浏览器就会推迟渲染,造成页面掉帧(浏览器每个帧都会进行样式计算、布局和绘制操作),页面刷新率低于24fps,形成视觉上的界面卡顿

2、fiber是一个执行单元,每次执行完一个执行单元,Reacta就会检查现在还剩多少时间,如果没有时间就将控制权让出去

四、关于setState是否为异步的解析

1、正常情况下,没有使用组件情况下,是同步更新的

但是不会立即获取到最新的state的值,因为这种情况调用setState只是单纯的将传入的state值放入UpdateQueen这条链表上,未执行更新

但内部会执行一个回调函数,才会真正的更新state,再重新渲染(无法立即获取值)

2、当使用组件时才是真正的异步更新模式,无法立即获取最新的状态,并且在更新和渲染时,会将整个过长放入eventloop中去执行 ,这时候才是真正的异步(无法立即获取值)

3、当使用flushSync()API书写setState时,react更新渲染完全同步,react会立即更新及渲染过程(可以立即获取值)

4、addEventLister()回调中setState(),非合成事件 (可以立即获取值)

5、setState()第二个参数回调函数中读取最新state值

五、fiber如何被打断

在reconciliation 阶段,指创建fiber的过程 :React16将Dom节点打散成了相互独立且有联系的一个个fiber对象,他们之间存在优先级关系,

在渲染时, 通过将一个个fiber任务打散在浏览器渲染的每一帧中 ,而Fiber实现了自己的组件调用栈,它以链表的形式遍历组件树,可以灵活的暂停、继续和丢弃执行的任务。

​ 实现方式是使用了浏览器的requestIdleCallback这一 API,可以让浏览器在空闲的时候执行回调,在回调参数中可以获取到当前帧剩余的时间,fiber 利用了这个参数,判断当前剩下的时间是否足够继续执行任务,如果足够则继续执行,否则暂停任务,并调用 requestIdleCallback 通知浏览器下次空闲的时候继续执行当前的任务。

六、(React新版本中)fiber为什么要废弃一些生命周期

在 fiber 中,

更新分为两个阶段,

1、reconciliation(real爱可塞累神=>和解) 的阶段,这个阶段在计算前后 dom 树的差异,耗时长,可以被打断

2、然后是 commit 的阶段,这个阶段将把更新渲染到页面上,一口气把更新渲染到页面上,不会被打断

因此:

reconciliation 的阶段会被打断,可能会导致 commit 前的这些生命周期函数多次执行。react 官方目前已经把 componentWillMountcomponentWillReceivePropscomponetWillUpdate 标记为 unsafe,并使用新的生命周期函数 getDerivedStateFromPropsgetSnapshotBeforeUpdate 进行替换。

mit 前的这些生命周期函数多次执行。react 官方目前已经把 componentWillMountcomponentWillReceivePropscomponetWillUpdate 标记为 unsafe,并使用新的生命周期函数 getDerivedStateFromPropsgetSnapshotBeforeUpdate 进行替换。

React-fiber架构的解释相关推荐

  1. React系列——React Fiber 架构介绍资料汇总(翻译+中文资料)

    原文 react-fiber-architecture 介绍 React Fibre是React核心算法正在进行的重新实现.它是React团队两年多的研究成果. React Fiber的目标是提高其对 ...

  2. 转载:React Fiber架构(浅显易懂)

    性能优化是一个系统性的工程,如果只看到局部,引入算法,当然是越快越好; 但从整体来看,在关键点引入缓存,可以秒杀N多算法,或另辟蹊径,探索事件的本质,可能用户要的并不是快-- React16启用了全新 ...

  3. React Fiber架构原理剖析

    一.概述 在 React 16 之前,VirtualDOM 的更新采用的是Stack架构实现的,也就是循环递归方式.不过,这种对比方式有明显的缺陷,就是一旦任务开始进行就无法中断,如果遇到应用中组件数 ...

  4. react fiber架构学习

    同步更新过程的局限 在v16版本以前,react的更新过程是通过递归从根组件树开始同步进行的,更新过程无法被打断,当组件树很大的时候就会出现卡顿的问题 react中的虚拟dom import Reac ...

  5. 从0实现react框架,React Fiber架构和Fiber Diff算法

    react框架是目前最为流行的前端框架之一,尤其在很多大厂,应用更为广泛.相对于一些mvvm框架,react上手需要一定的技术基础,但掌握后,编码体验和性能是很不错的.react整体思想是函数式编程, ...

  6. React Fiber架构原理

    一,概述 在 React 16 之前,VirtualDOM 的更新过程是采用 Stack 架构实现的,也就是循环递归方式.这种对比方式有一个问题,就是一旦任务开始进行就无法中断,如果应用中组件数量庞大 ...

  7. react 日期怎么格式化_手写React的Fiber架构,深入理解其原理

    熟悉React的朋友都知道,React支持jsx语法,我们可以直接将HTML代码写到JS中间,然后渲染到页面上,我们写的HTML如果有更新的话,React还有虚拟DOM的对比,只更新变化的部分,而不重 ...

  8. react源码中的fiber架构

    先看一下FiberNode在源码中的样子 FiberNode // packages/react-reconciler/src/ReactFiber.old.js function FiberNode ...

  9. 【React】1077- React Fiber架构浅析

    1.浏览器渲染 为了更好的理解 React Fiber, 我们先简单了解下渲染器进程的内部工作原理. 参考资料: 从内部了解现代浏览器(3)[1] 渲染树构建.布局及绘制[2] 1.1 渲染帧 帧 ( ...

  10. React Fiber 原理介绍

    欢迎关注我的公众号睿Talk,获取我最新的文章: 一.前言 在 React Fiber 架构面世一年多后,最近 React 又发布了最新版 16.8.0,又一激动人心的特性:React Hooks 正 ...

最新文章

  1. 云服务器 架设传奇_传奇手游-战神引擎架设教程
  2. key的数据类型是字符串
  3. 内存管理,数据类型的基本使用与基本运算符(python2中与用户交互)
  4. SpringMVC的数据响应
  5. 19 删除链表的倒数第N个
  6. 1787: [Ahoi2008]Meet 紧急集合
  7. post和get两种提交方式的区别
  8. python好学么数学_Python难学吗,本人数学和英语都很差,想学,都是兴趣爱好
  9. Matplotlib 中文用户指南 8.1 屏幕截图
  10. 为什么java jvm.dll_Windows下java、javaw、javaws以及jvm.dll等进程的区别
  11. 在线数理思维教育品牌“火花思维”完成4000万美元C轮融资
  12. gtkterm ubuntu下好用的串口工具使用心得-转
  13. 磁盘:最容易被忽略的性能洼地
  14. 【原创】Structure from Motion (SfM)算法测试---3D重建简介
  15. 小学生学AD16(入门级别,看这篇就够了)
  16. linux 隐藏命令参数,linux – 在ps中隐藏命令的参数
  17. 10·24|程序员节!
  18. Java字符串相似度匹配
  19. struct2破绽及升级
  20. 有声电子书成市场新宠 影响人们阅读习惯

热门文章

  1. HJL-93/AY AC220V数字式交流三相电流继电器
  2. Protobuf简单使用
  3. terminate called after throwing an instance of ‘YAML::TypedBadConversion<int>‘ what(): bad conver
  4. 区块链 以太坊 多层调用,获取调用者 msg.sender
  5. php k线15分钟 30分钟,成功率极高的“分时K线战法”:15分钟K线战法+30分钟K线战法...
  6. 智能优化算法:海鸥算法原理及Matlab代码
  7. 【zz】陈硕:当析构函数遇到多线程──C++ 中线程安全的对象回调
  8. erlang底层c定时器设计-Erlang源码学习二
  9. Contest3121 - 2021级新生个人训练赛第26场_问题 F: 乐乐的数字
  10. win10文件夹加密_Win10 系统优化软件 Windows 10 Manager v3.2.0