react渲染

react渲染机制

注意:知道这个如何在面试中成为亮点:当问到vue渲染的时候,可以穿插着和react渲染做对比,这样才显示出两个框架都熟悉

我们通常认为的渲染的过程是指:从template模版编译到最后dom更新,这整个阶段都可以认为是渲染。但是在react中其实应该更细一点,我们可以把react分为渲染和提交,这里的提交就是更新到dom上。

react渲染主要分为两个阶段,三块功能 (1)schedule调度 (2)reconcile协调 (3)render渲染

一、schedule调度

1.1 什么是调度?为什么需要调度?

想象一个场景,当我们只有一个js引擎来执行的时候,如果有多个任务,那么为了保证尽可能好的用户体验丝滑,我肯定需要对这些要处理的任务进行优先级划分,等级高的我优先执行。这种处理不同优先级任务放入到引擎中执行的机制就是调度。此外,还有一种场景,当我们把某一个优先级高的任务放入到引擎中执行的时候,如果这个任务执行时间是100ms且同步执行不可中断,那么就会产生延迟(浏览器中的延迟定义是: 浏览器渲染周期是60hz,一秒钟执行60次,每次执行16.6ms,如果长时间霸占引擎超过100ms,就会产生用户感知。)因此需要在16.6ms的时候如果一个任务执行不完,那么先中断,等待下个浏览器渲染周期到来之后再继续执行。而不是一直霸占着引擎直到执行完毕。这种处理单个任务中断&继续执行的机制也是调度。

这种调度其实是一种模式,即Concurrent并行模式(之前Legacy mode 同步阻塞模式,会阻塞渲染)

总结:调度的功能就是:1.多个任务的优先级划分;2.当个任务的时间片内的任务中断和恢复

浏览器相关知识
知识点1 : 理解浏览器一帧周期

浏览器以16.6ms为周期内,做了哪些事情?

1.事件处理时期

2.js执行时期

3.视图绘制时期

4.浏览器空闲时期

知识点2: 认识浏览器API - requestIdleCallback( callback, options )

idle是空闲的意思,requestIdleCallback就是请求空闲函数,该函数是浏览器提供给外界在浏览器一帧周期内中"空闲时间周期"自动执行的函数,通常用来执行不重要的任务,以确保这些任务的执行不会阻塞主线程,进而提高页面的响应性。

js 复制代码
// deadlineObj中主要的参数
{
   timeRemaining: () => {} // 返回当前帧还剩的时间
   didTimeout: true // 表示回调函数是否在timeout超时时间之前就已经执行
}
const ID = requestIdleCallback((deadlineObj) => { // deadlineObj为当前帧对象,可以通过该对象查看当前帧的一些情况,例如当前帧还剩下多少空闲时间
  deadlineObj.deadlineObj() // 当前帧剩余的毫秒数
}, {timeout: 1000}) 
// 这里的 timeout 是指,当过了timeout之后,该回调函数依然没有执行的话,那么就需要将这个回调放入到事件循环队列中执行
window.cancelIdleCallback(ID) 
// 通过将对应的ID传入调用的window.cancelIdleCallbeck,则可以取消调用
//
//  注意:如果多个回调调用requestIdleCallback的话,那么就都会放入到一个统一队列中,先进先出。

举例:

js 复制代码
requestIdleCallback((deadline) => { 
    console.log(deadline.timeRemaining())
}, {timeout: 1000})

打印结果:剩余时间是35.6ms,有人会问,不是一帧16.6ms吗,怎么剩余时间比一帧周期时间还要长呢? 因为我们对"空闲时间"的认知和定义过于狭隘:

(1)当出现短时间内多次屏幕刷新的时候,那么浏览器会严格按照一帧16.6ms最小间隔去执行事件处理&屏幕刷新,这就是最小刷新间隔,这里存在一个空闲时间

(2)如果屏幕空闲时间很长,那么下一次刷新可能要等很久(用户不交互就不刷新),那么浏览器也不能一直处于空闲时间,因此也要给他一个最大时间限制 - 50ms

知识点3: 认识浏览器API - requestAnimationFrame

请求动画帧这个API本意上是专门用来处理动画的,因为之前如果使用定时器来做动画(每个100ms变换坐标来实现位移的效果)此时就会出现抖动现象,但是如果使用请求动画帧这个API就会丝滑很多。 那么为什么请求动画帧比定时器丝滑?因为他在特定的时间点进行代码执行,而定时器与绘制频率周期没有保持共振,这就导致前两个周期绘制一次,然后在等一个周期绘制一次,在等3个周期绘制一次。这样就会导致下个绘制周期动画不变,造成视觉上感知到短暂静止,连续起来就会形成卡顿。而绘制动画帧就就是保证每次渲染都会执行,这样的严格卡点就会感觉很丝滑。

1.2 怎么调度(react中调度的机制流程)

设定一下任务优先级 react在内部定义了 5 种类型的优先级,以及对应的超时时间timeout

ImmediatePriority, 直接优先级,对应用户的 click、input、focus 等操作; timeout为 -1,表示任务要尽快处理; UserBlockingPriority,用户阻塞优先级,对应用户的 mousemove、scroll 等操作;timeout 为 250 ms; NormalPriority,普通优先级,对应网络请求、useTransition 等操作; timeout 为 5000 ms; LowPriority,低优先级(未找到应用场景);timeout 为 10000 ms; IdlePriority,空闲优先级,如 OffScreen; timeout 为 1073741823 ms;

5 种优先级的顺序为: ImmediatePriority > UserBlockingPriority > NormalPriority > LowPriority > IdlePriority。

相关推荐
辻戋4 分钟前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保6 分钟前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun1 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp1 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.2 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl4 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫6 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友6 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理7 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻7 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js