react理念(一)

embedded/2024/10/18 3:31:10/

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节点。


http://www.ppmy.cn/embedded/126389.html

相关文章

【数据结构】string(C++模拟实现)

string构造 string::string(const char* str):_size(strlen(str)) {_str new char[_size 1];_capacity _size;strcpy(_str, str); }// s2(s1) string::string(const string& s) {_str new char[s._capacity 1];strcpy(_str, s._str);_size s._size;_capacity s._cap…

解决 Django 数据库迁移报错:无法添加带有 `auto_now_add=True` 的字段20241008

解决 Django 数据库迁移报错:无法添加带有 auto_now_addTrue 的字段 引言 在使用 Django 进行开发时,数据库迁移是不可避免的一部分。然而,添加新字段特别是带有 auto_now_addTrue 的日期时间字段时,可能会遇到一些令人头疼的错…

『Mysql进阶』Mysql SQL语句性能分析(七)

目录 什么是Profile? 开启Profile功能 基本使用 分析案例 什么是Profile? Query Profiler是 MySQL 自带的一种 Query 诊断分析工具 ,通过它可以分析出一条 SQL 语句的 硬件性能瓶颈 在什么地方。 通常我们是使用的 explain ,…

「3.3」虫洞 Wormholes

多组数据不清零——见祖宗 「3.3」虫洞 Wormholes 问题背景 「一本通3.3 练习2」 题目描述 John 在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John 的每…

Ubuntu安装Apache教程

系统版本:Ubuntu版本 23.04 Ubuntu是一款功能强大且用户友好的操作系统,而Apache是一款广泛使用的Web服务器软件。在Ubuntu上安装Apache可以帮助用户搭建自己的网站或者进行Web开发。为大家介绍如何在Ubuntu上安装Apache,并提供详细的教程和操…

4 机器学习之归纳偏好

通过学习得到的模型对应了假设空间中的一个假设。于是,图1.2的西瓜版本空间给我们带来一个麻烦:现在有三个与训练集一致的假设,但与它们对应的模型在面临新样本的时候,却会产生不同的输出。例如,对(色泽青绿…

rust使用教程详解

欢迎来到 Rustlings。该项目包含一些小练习,让您习惯阅读和编写 Rust 代码。这包括阅读和响应编译器消息! 建议在阅读Rust 官方书籍(学习 Rust 最全面的资源)的同时做 Rustlings 练习 📚️ Rust By Example是另一个推…

DAY7 继承多态

继承 目的 提高代码的重用性,减少一些重复代码的书写 权限修饰符 就是是用来限制类中的成员(成员变量、成员方法、构造器)能够被访问的范围。 private 只能本类 缺省 本类、同一个包中的类 protected 本类,同一个包中的类、子…