欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

为什么在 React 16 版本中 render 阶段放弃了使用递归?

程序员文章站 2022-07-02 19:21:26
因为主流浏览器的刷新频率为60Hz,即每(1000ms /60Hz)16.6ms浏览器刷新一次。JS可以操作DOM,GUI渲染线程与JS线程是互斥的。所以JS脚本执行和浏览器布局、绘制不能同时执行。超过16.6ms就会让用户感知到卡顿。在16之前的版本中采用递归执行。递归耗内存,它使用 JavaScript 自身的执行栈,更新一旦开始,中途就无法中断。当VirtualDOM 树的层级很深时,virtualDOM 的比对就会长期占用 JavaScript 主线程,递归更新的时间就会超过16ms,由于....

因为主流浏览器的刷新频率为60Hz,即每(1000ms /60Hz)16.6ms浏览器刷新一次。JS可以操作DOM,GUI渲染线程与JS线程是互斥的。所以JS脚本执行和浏览器布局、绘制不能同时执行。超过16.6ms就会让用户感知到卡顿。

  • 在16之前的版本中采用递归执行。递归耗内存,它使用 JavaScript 自身的执行栈,更新一旦开始,中途就无法中断。当VirtualDOM 树的层级很深时,virtualDOM 的比对就会长期占用 JavaScript 主线程,递归更新的时间就会超过16ms,由于 JavaScript 又是单线程的无法同时执行其他任务,所以在比对的过程中无法响应用户操作,无法即时执行元素动画,造成了页面卡顿的现象。
  • 而React16架构可以分为三层:Scheduler,Reconciler,Renderer,与之前不同的是Reconciler和Renderer不再交替执行,而是当Scheduler将任务交给Reconciler后,Reconciler会为变化的虚拟DOM打上代表增/删/更新的标记,整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer。并且采用双缓存用作统一替换,用户也不会看到更新不完全的真实dom。它放弃了 JavaScript 递归的方式进行 virtualDOM 的比对,而是采用循环模拟递归。而且比对的过程是利用浏览器的空闲时间完成的,不会长期占用主线程,这就解决了 virtualDOM 比对造成页面卡顿的问题。

解决方案:

1. react16后使用 fiber架构可拆分,可中断任务

  • 可重用各分阶段任务,且可以设置优先级
  • 可以在父子组件任务间前进后退切换任务
  • render方法可以返回多元素(即可以返回数组)
  • 支持异常边界处理异常

采用循环模拟递归。而且比对的过程是利用浏览器的空闲时间完成的,不会长期占用主线程,这就解决了 virtualDOM 比对造成页面卡顿的问题。

2. 官方实现了自己的任务调度库,这个库就叫做 Scheduler。

window 对象中提供了 requestIdleCallback API ,可以实现用浏览器的空闲时间执行任务,但是它兼容性差。不过目前属于还在实验中的功能。
链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback

本文地址:https://blog.csdn.net/weixin_40599109/article/details/112580864