likes
comments
collection
share

「react自顶向下」为什么需要时间分片和异步更新?

作者站长头像
站长
· 阅读数 70

一、React设计的理念

快速响应: React15的老架构违背了快速响应的设计理念。

二、浏览器渲染原理

这篇文章里面详细的解释了浏览器的渲染流程

一文看懂浏览器解析流程

三、React15(老架构)

1.组成

React15架构可以分为两层:

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

2.Reconciler(协调器)

Reconciler(协调器)是 React 中的一个重要概念,它负责协调和管理组件的更新过程。

在 React 中,组件的更新涉及到以下几个阶段:组件接收新的属性(props)、组件更新状态(state)、生成新的虚拟 DOM、与旧的虚拟 DOM 进行比较、并最终将更改应用到实际的 DOM 上。这个更新过程需要被有效地管理和调度,以保证性能和用户体验。

Reconciler 的主要责任如下:

  1. 创建和更新虚拟 DOM:Reconciler 负责根据组件的状态和属性,以及组件树的结构,生成新的虚拟 DOM 树。当组件的状态或属性发生变化时,Reconciler 会重新计算组件的虚拟 DOM,以反映最新的变化。
  2. 比较虚拟 DOM:Reconciler 使用 diff 算法(协调算法)比较新的虚拟 DOM 树与旧的虚拟 DOM 树之间的差异。通过比较,Reconciler 可以找出需要更新的部分,以减少对实际 DOM 的操作。
  3. 调度更新:Reconciler 负责将组件的更新任务调度到适当的时间和优先级。它会考虑当前的浏览器任务队列,优化任务的执行顺序和频率,以提高性能和响应性。例如,它可以将更新任务拆分成多个小任务,在多个时间片内逐步执行,避免长时间阻塞主线程。
  4. 与 Renderer 交互:Reconciler 与 Renderer(渲染器)紧密合作,将虚拟 DOM 的变化应用到实际的 DOM 上。Reconciler 会将需要更新的部分信息传递给 Renderer,由 Renderer 执行实际的 DOM 操作。

3.Renderer(渲染器)

Renderer(渲染器)是 React 中的一个关键概念,它负责将虚拟 DOM 的变化应用到实际的 DOM 上,并最终呈现在浏览器中。

在 React 中,虚拟 DOM 是一个轻量级的内存中的 DOM 表示,它与真实的 DOM 结构相对应。当组件的状态或属性发生变化时,Reconciler 会生成新的虚拟 DOM 树,并通过比较算法找出需要更新的部分。而 Renderer 的任务是将这些变化应用到实际的 DOM 上,使界面呈现出相应的效果。

具体来说,Renderer 的主要责任如下:

  1. 创建和更新实际 DOM:Renderer 负责根据虚拟 DOM 的描述,创建和更新实际的 DOM 元素。它会根据虚拟 DOM 的类型、属性和子元素,创建相应的 HTML 元素,并将其添加到 DOM 树中。对于已存在的元素,Renderer 会更新其属性和内容,以反映虚拟 DOM 的变化。
  2. 处理事件和用户交互:Renderer 还负责处理用户的事件和交互操作。它会注册事件处理函数,以便在用户触发事件时执行相应的逻辑。当用户与界面进行交互时,Renderer 可以根据需要更新虚拟 DOM,并将更改应用到实际 DOM 上。
  3. 执行 DOM 操作:Renderer 会执行实际的 DOM 操作,包括元素的创建、属性的设置、内容的更新、元素的添加或移除等。这些操作会直接影响浏览器中的页面呈现。

需要注意的是,Renderer 是与平台相关的部分,React 提供了不同的 Renderer 实现,用于适配不同的平台和环境。例如,React DOM 是用于 Web 的 Renderer,React Native 是用于移动端的 Renderer。这样,React 能够在不同的平台上提供一致的开发体验,同时根据不同的平台特性进行优化。

总结起来,Renderer 负责将虚拟 DOM 的变化应用到实际的 DOM 上,实现界面的渲染和交互。它是 React 的重要组成部分,与 Reconciler 协同工作,提供了高效、可靠的组件渲染机制。

4.React15架构的缺点:递归更新

React 15 架构的一个主要缺点是递归更新。在 React 15 及之前的版本中,组件的更新是通过递归的方式进行的。这意味着当组件的状态或属性发生变化时,React 会从根组件开始,递归地遍历整个组件树,并执行更新操作。

递归更新的方式在一些情况下可能会导致性能问题和不必要的重复计算,主要体现在以下几个方面:

  1. 大型组件树的更新效率低下:如果应用中存在大型组件树,递归更新的方式会导致整个组件树的更新操作。这可能会占用大量的计算资源和时间,并且无法避免对不需要更新的组件进行重复计算,导致性能下降。
  2. 子组件的无谓更新:在递归更新中,父组件的更新会导致所有子组件也被更新,即使这些子组件的状态或属性并未发生变化。这会导致不必要的虚拟 DOM 比较和实际 DOM 操作,降低了性能。
  3. 长时间的主线程阻塞:递归更新可能会在主线程上占用较长时间,导致用户界面的卡顿和不流畅的体验。由于更新操作是同步执行的,长时间的计算或渲染任务会阻塞主线程的其他任务,影响用户交互和动画的流畅性。

为了解决这些问题,React 16 引入了 Fiber 架构,改变了更新的方式,从递归更新转变为基于 Fiber 的可中断、增量更新。Fiber 架构通过任务的切片、优先级调度和增量渲染等技术,提供了更高效、可控的组件更新机制,提升了 React 应用的性能和用户体验。

四、React16新架构-fiber

1.组成

React16架构可以分为三层:

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

可以看到,相较于React15,React16中新增了Scheduler(调度器) ,让我们来了解下他。

2.Scheduler(调度器)

Scheduler(调度器)是 React 中的一个关键概念,它负责管理和调度任务的执行顺序和优先级,以提高应用的性能和响应性。

在 React 中,调度器与 Reconciler(协调器)紧密合作,协同工作以实现可中断的异步更新。调度器的主要任务如下:

  1. 任务切片和优先级调度:调度器将更新任务(例如组件的渲染或状态的更新)切分成多个小的任务单元,并按照优先级进行调度。每个任务单元被称为一个时间片(Time Slice),调度器可以在每个时间片结束时中断任务的执行,以处理其他高优先级的任务或事件。
  2. 任务优先级管理:调度器根据任务的优先级,确定任务的执行顺序。较高优先级的任务会被优先执行,以保证重要的任务能够及时完成,提高应用的响应性。调度器还能够动态地调整任务的优先级,以适应不同情况下的性能需求。
  3. 同步和异步任务的处理:调度器可以处理同步和异步任务。同步任务是立即执行的任务,而异步任务是通过可中断的方式执行的任务。调度器可以在每个时间片内逐步执行异步任务,避免长时间阻塞主线程,提高应用的性能和响应性。
  4. 任务调度的灵活性:调度器提供了一些 API,使开发者能够对任务的调度行为进行控制和干预。例如,开发者可以使用 requestIdleCallback API 来在空闲时间执行任务,或者使用 React 提供的批处理 API 来控制任务的执行方式。

调度器的引入使得 React 应用能够更好地适应不同的设备和网络环境,提供更好的用户体验。通过任务的切片、优先级调度和可中断执行,调度器能够平衡任务的执行和用户交互,保证应用的性能和响应性。

3.Reconciler(协调器)

同上

4.Renderer(渲染器)

同上

五、「react自顶向下」系列文章下篇预告:

在react16中新增的Scheduler实现了时间分片和异步更新,其中最重要的就是fiber架构,下一篇我们将会介绍一下fiber。

转载自:https://juejin.cn/post/7243342597002133561
评论
请登录