react理念(一)

发布于:2024-10-12 ⋅ 阅读:(5) ⋅ 点赞:(0)

react

react理念

当遇到大计算量的操作或者设备性能不足的页面掉帧,会导致卡顿,发送网路请求的时候,需要等待数据返回才能进一步操作导致不能快速响应。叫做cpu的瓶颈和io的瓶颈

cpu的瓶颈

主流浏览器刷新频率为60hz(requestAnimation), js可以操作dom,gui渲染线程和js线程是互斥的,js脚本执行和浏览器布局,绘制不能同时执行。
所以在一个hz的刷新过程中,需要完成脚本执行,样式布局,样式绘制。当js执行时间过长,刷星就没有时间执行样式布局和样式绘制了。js脚本执行时间过长,页面掉帧,造成卡顿。react解决的思路是,在浏览器的每一帧中,预留一些时间给js线程,react利用这部分时间来更新组件。当预留的时间不足的时候,react将线程控制权交还给浏览器让他有时间来渲染ui,react等待下一帧时间来继续被中断的工作。
Concurrent Mode(并发模式),开启并发模式后,长任务会被拆分到不同的task中。这样浏览器就会有时间执行样式布局和绘制。减少掉帧的可能性。解决cpu瓶颈的关键是时间切片,时间切片的关键是将同步的更行变化为中断的一部更新。

io的瓶颈

网络延迟是客观存在的,现在当前页面停留一段时间,这段时间被用来请求数据,当这段时间足够段的时候,用户是没有感知的。react实现了这些功能以及配套的hook。实现这种功能,需要将同步的更新转换为可中断的异步更新。

react15

react15架构包含两层,协调器找出变化的组件,渲染器将变化的组件渲染到页面上。

协调器
  • 调用函数组件,或class组件的render方法,将返回的jsx转换为虚拟dom
  • 将虚拟dom和上次的虚拟dom来进行对比
  • 通过对比找出本次更新中变化的虚拟dom
  • 通知renderer将变化的虚拟dom渲染到页面上
渲染器

由于react支持跨平台,不同平台会有不同的renderer。浏览器环境渲染-reactdom。 reactnative渲染-渲染app原生组件。reacttest渲染-纯js对象用于测试。reactart渲染器-渲染到canvas,svg或者vml
每次更新发生的时候,渲染器接收到协调器的通知。

架构的缺点,mount和update都会递归更新组件,递归执行,更新一旦开始,中途无法中断,当层级很深的死后,递归更新超过了16ms,用户就会变得卡顿,可以使用中断的异步更新代理同步的更新。渲染器和协调器是交替工作的,整个过程是同步的,所以用户看来是同时更新的。当发生中断的时候,页面的渲染也会出现中断。

react16

react16分为三层。调度器,负责任务的优先级,高优任务优先进入协调器,协调器负责找出变化的组件,渲染器负责将变化的组件渲染到页面上。

调度器

以浏览器是否有剩余时间作为任务中断的标准,需要一种机制,当浏览器有剩余时间的时候进行通知。[requestIdleCallback=> 这个函数在浏览器空闲的时候被调用,开发者能够在主事件循环上执行后台和低优先级工作,如果回调函数指定了超时时间timeout,有可能为了在超时前执行函数而打乱执行顺序。可以在空闲回调函数中调用requestIdleCallback,以便在下次事件循环之前调度另一个回调]。由于兼容性和触发频率不稳定,等很多因素的影响,当浏览器切换到tab的时候,之前注册的requestIdleCallback触发的频率会变得很低。
所以react实现了功能更加完备的requestIdleCallback polyfill。在空闲时触发回调的功能外,还提供了多种调度优先级供任务设置。scheduler是独立于react的库

协调器

在react15中,是用来递归处理虚拟dom的
在react 16中, 更新工作从递归变成了可以中断的循环过程。每次循环都会调用shouldYield判断当前是否有剩余时间。
react16,协调器和渲染器不是交替工作的,当调度器将任务交给协调器之后,协调器就会为变化的虚拟dom打上增删改更新的标记,整个调度器和协调器的工作都在内存中进行,只有当组件完成协调器的工作,才会同意交给调度器。

渲染器

渲染器根据协调器打的标签,同步执行对应的dom操作
调度器和协调器的步骤,会被中断,中断原因(1. 更高优先级的任务需要优先更新,2. 当前帧没有剩余时间),因为是与平台无关的,所以react为他们单独发了一个包。

fiber

代数效应: 代数效应是函数式编程中的一个概念,将副作用从函数中分离出来,使用就是hooks
从react15到16,协调器重构,能够将同步更新的架构变成了异步可中断更新。
异步可中断更新:更新在执行过程中可能会被打断,浏览器时间分片用尽或者有更高优任务插队,当可以继续执行时回复之前执行的中间状态。
浏览器原生就支持类似的实现。就是generator。但是generator是类似于async的,可以传染,使用generator则上下文中的其他函数也需要作出改变,这样负担比较重。generator执行的中间状态是上下文关联的。
只考虑单一优先级任务的中断与继续的情况下generator可以很好的实现异步可同步更新。但是考虑到高优先级任务插队的情况,generator执行的中间状态是上下文关联的,所以无法进行复用之前的值,需要重新计算。
fiber叫做纤程,在js中,协程的实现是generator,可以将fiber和generator理解为代数效应在js中的体现。
react fiber可以理解为,react内部实现的一套状态更新机制,支持任务不同优先级,可以中断和回复,并且回复后可以服用之前的中间状态,每个任务更新单元就是react 元素对应的fiber节点。