返回
从 React 调度机制管窥 React 异步可中断模式
前端
2023-12-30 10:31:54
前言
在前面的文章中,我们提到在协调之前还有一个调度步骤。然而,在目前使用 ReactDOM.render 这个 API 的情况下,调度和过去版本并没有太大区别。React v17 是一个过渡版本,直到 React v18 才正式启用 React 的异步可中断模式(Concurrent Mode)。
React 异步可中断模式的提出是为了解决现有 React 的两个痛点:
- 浏览器渲染的滞后性: 浏览器每秒只能渲染 60 帧,因此当 React 更新 UI 时,如果一个更新需要很长时间,那么这个更新就会阻塞浏览器的渲染,导致页面卡顿。
- 用户交互的不可中断性: 当 React 更新 UI 时,整个更新过程是不可中断的,这意味着用户在更新过程中无法进行任何操作。
React 异步可中断模式通过引入新的调度机制来解决这两个问题,该机制允许浏览器在更新 UI 时中断并恢复渲染,从而提高页面的流畅性和交互性。
调度机制
在 React 中,调度机制负责将更新事件分发给各个组件,并决定这些更新何时被提交到浏览器进行渲染。调度机制由以下几个部分组成:
- 事件循环(Event Loop): 事件循环是浏览器提供的一个机制,用于处理来自用户的输入、定时器和网络请求等事件。当有事件发生时,浏览器会将事件放入事件队列中,然后按照一定的顺序处理这些事件。
- 调度器(Scheduler): 调度器是 React 内部的一个模块,用于管理 React 的更新事件。当组件发生更新时,React 会将更新事件放入调度器中。
- 协调器(Reconciler): 协调器是 React 内部另一个模块,用于将更新事件提交到浏览器进行渲染。当调度器将更新事件交给协调器后,协调器会将更新事件与组件的当前状态进行比较,并生成一个新的虚拟 DOM 树。然后,协调器将新的虚拟 DOM 树与旧的虚拟 DOM 树进行比较,并生成一个补丁包(Patch)。最后,协调器将补丁包发送给浏览器,浏览器会根据补丁包更新页面的内容。
调度行为
在 React 中,调度器根据以下几个因素来决定是否中断更新:
- 更新的优先级: React 将更新分为高优先级和低优先级。高优先级的更新会立即被调度,而低优先级的更新会稍后被调度。
- 浏览器的渲染状态: 如果浏览器正在渲染,那么调度器会中断更新,直到浏览器完成渲染。如果浏览器没有在渲染,那么调度器会继续调度更新。
- 用户交互: 如果用户正在与页面进行交互,那么调度器会中断更新,直到用户停止交互。
调度策略
在 React 中,调度器提供了几种不同的调度策略,开发人员可以根据需要选择不同的调度策略。目前 React 中提供的调度策略有:
- Immediate Mode: 这种调度策略会立即将所有更新调度到浏览器进行渲染。这种策略适用于那些对性能要求不高,但需要立即更新 UI 的场景。
- Deferred Mode: 这种调度策略会将低优先级的更新延迟到浏览器空闲时再进行渲染。这种策略适用于那些对性能要求较高,但可以接受 UI 更新延迟的场景。
- Concurrent Mode: 这种调度策略是 React v18 中引入的,它允许浏览器在更新 UI 时中断并恢复渲染。这种策略适用于那些对性能要求非常高,并且需要保持 UI 交互性的场景。
总结
React 的调度机制是一个复杂而精巧的系统,它在保证 React 应用性能的同时,也为 React 异步可中断模式提供了基础。通过深入理解 React 的调度机制,我们可以更好地掌握 React 的工作原理,并开发出更加高效、流畅的 React 应用。