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。

相关推荐
繁依Fanyi17 分钟前
用 CodeBuddy 实现「IdeaSpark 每日灵感卡」:一场 UI 与灵感的极简之旅
开发语言·前端·游戏·ui·编辑器·codebuddy首席试玩官
来自星星的坤2 小时前
【Vue 3 + Vue Router 4】如何正确重置路由实例(resetRouter)——避免“VueRouter is not defined”错误
前端·javascript·vue.js
寧笙(Lycode)3 小时前
React系列——nvm、node、npm、yarn(MAC)
react.js·macos·npm
香蕉可乐荷包蛋6 小时前
浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
前端·javascript·es6
未来之窗软件服务7 小时前
资源管理器必要性———仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide
liuyang___8 小时前
第一次经历项目上线
前端·typescript
西哥写代码8 小时前
基于cornerstone3D的dicom影像浏览器 第十八章 自定义序列自动播放条
前端·javascript·vue
清风细雨_林木木8 小时前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
FungLeo9 小时前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
不灭锦鲤9 小时前
xss-labs靶场第11-14关基础详解
前端·xss