【react】react 15-16架构变化

react 15-16架构变化

相关文章

react 架构变化


一、React15 架构

React15 架构可以分为两层:

  • Reconciler(协调器)—— 负责找出变化的组件
  • Renderer(渲染器)—— 负责将变化的组件渲染到页面上

Reconciler(协调器)

我们知道,在React中可以通过this.setState、this.forceUpdate、ReactDOM.render等 API 触发更新。

每当有更新发生时,Reconciler会做如下工作:

  • 调用函数组件、或 class 组件的render方法,将返回的 JSX 转化为虚拟 DOM
  • 将虚拟 DOM 和上次更新时的虚拟 DOM 对比
  • 通过对比找出本次更新中变化的虚拟 DOM
  • 通知Renderer将变化的虚拟 DOM 渲染到页面上

React官方解释

Renderer(渲染器)

由于React支持跨平台,所以不同平台有不同的Renderer。我们前端最熟悉的是负责在浏览器环境渲染的Renderer —— ReactDOM。

除此之外,还有:

  • ReactNative渲染器,渲染 App 原生组件
  • ReactTest渲染器,渲染出纯 Js 对象用于测试
  • ReactArt渲染器,渲染到 Canvas, SVG 或 VML (IE8)

在每次更新发生时,Renderer接到Reconciler通知,将变化的组件渲染在当前宿主环境。

React官方解释

二、React15 架构的缺点

在Reconciler中,mount的组件会调用mountComponent,update的组件会调用updateComponent。这两个方法都会递归更新子组件。

递归更新的缺点

由于递归执行,所以更新一旦开始,中途就无法中断。当层级很深时,递归更新时间超过了 16ms,用户交互就会卡顿。

三、React16 架构

React16 架构可以分为三层:

  • Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler
  • Reconciler(协调器)—— 负责找出变化的组件
  • Renderer(渲染器)—— 负责将变化的组件渲染到页面上

可以看到,相较于 React15,React16 中新增了Scheduler(调度器)

Scheduler(调度器)

既然我们以浏览器是否有剩余时间作为任务中断的标准,那么我们需要一种机制,当浏览器有剩余时间时通知我们。

其实部分浏览器已经实现了这个 API,这就是requestIdleCallback。但是由于以下因素,React放弃使用:

  • 浏览器兼容性
  • 触发频率不稳定,受很多因素影响。比如当我们的浏览器切换 tab 后,之前 tab 注册的requestIdleCallback触发的频率会变得很低

基于以上原因,React实现了功能更完备的requestIdleCallbackpolyfill,这就是Scheduler。除了在空闲时触发回调的功能外,Scheduler还提供了多种调度优先级供任务设置。

Scheduler是独立于React的库

Reconciler(协调器)

我们知道,在 React15 中Reconciler是递归处理虚拟 DOM 的。让我们看看React16 的 Reconciler。

我们可以看见,更新工作从递归变成了可以中断的循环过程。每次循环都会调用shouldYield判断当前是否有剩余时间。

那么 React16 是如何解决中断更新时 DOM 渲染不完全的问题呢?

在 React16 中,Reconciler与Renderer不再是交替工作。当Scheduler将任务交给Reconciler后,Reconciler会为变化的虚拟 DOM 打上代表增/删/更新的标记:

ReactSideEffectTags.js文件定义了一组表示 React 更新过程中副作用的标记常量。副作用标记用于标识组件更新时需要进行的具体操作,例如添加、删除、更新 DOM 元素等。这些标记常量通常会在 React 内部的调度和协调过程中使用。

以下是 ReactSideEffectTags.js 中可能定义的一些常量及其含义:

  • NoEffect: 表示没有副作用,通常用于表示某个操作不会引起组件更新。
  • Peristed: 表示组件的状态已经被持久化,通常用于 React 的服务端渲染过程中。
  • Placement: 表示需要将组件添加到 DOM 中。
  • Update: 表示需要更新组件的 props 或 state。
  • Deletion: 表示需要从 DOM 中删除组件。
  • ContentReset: 表示需要重置组件的内容。
  • Callback: 表示需要执行回调函数。

整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer。

Renderer(渲染器)

Renderer根据Reconciler为虚拟 DOM 打的标记,同步执行对应的 DOM 操作。

四、总结

通过本节我们知道了React16采用新的Reconciler。而Reconciler内部采用了Fiber的架构。

Fiber是什么?他和Reconciler或者说和React之间是什么关系?下一篇文章继续讲。


【react】react 15-16架构变化
https://www.cccccl.com/20240306/react/react 15-16架构变化/
作者
Jeffrey
发布于
2024年3月6日
许可协议