← 返回目录

第 25 卷

第 25 / 28 卷日期:

• 设计前提是「模板编译优化」:Vue 基于模板语法开发,编译阶段会对模板进行静态分析(如标记

useMemo)。

2. 子节点对比策略差异(核心差异点)

子节点对比是 diff 算法的核心,两者在列表子节点对比和非列表子节点对比上均有差异,其中列表对比差异最为显著:

(1)列表子节点对比:key 作用与移动优化逻辑

• React:

• key 的核心作用是「建立新旧节点的映射关系」,用于判断节点的“新增/删除/移动”。但 React

对列表节点移动的优化较为基础:

  • 1. 遍历新列表,用 key 构建“key-新节点”映射表;
  • 2. 遍历旧列表,通过 key 查找新列表中的对应节点:不存在则标记删除,存在则记录位置;
  • 3. 遍历新列表,查找旧列表中不存在的节点标记新增;

• 4. 对于需要移动的节点,通过“最长递增子序列”计算最小移动步数(React16+ 引入,优化移动

效率),但整体逻辑仍服务于 Fiber 的可中断遍历。

  • 局限:当列表节点数量庞大且移动频繁时,对比效率受 Fiber 调度开销影响,略低于 Vue。

• Vue:

• Vue2 和 Vue3 的列表 diff 均对“移动优化”做了深度适配,尤其是 Vue3 的“最长递增子序列”优

化更精准:

• 1. Vue2:采用“双指针法”遍历新旧列表,通过 key 对比节点,同时记录节点移动、新增、删除

状态,对比过程一次性完成,无调度开销;

• 2. Vue3:在 Vue2 基础上优化,通过“最长递增子序列”确定无需移动的节点,仅对其他节点进行

移动操作,进一步减少 DOM 操作次数;

  • 优势:同步对比+精准移动优化,在列表更新场景下(如长列表滚动加载、频繁排序)效率更高。

(2)非列表子节点对比:静态节点处理差异

• React:无编译阶段的静态节点标记,即使节点属性和内容完全不变(如静态文本、固定样式节

点),每次 diff 仍会对比其属性和子节点(除非通过 React.memo 或 PureComponent 手动优化),存在冗余对比开销。

• Vue:编译阶段会标记“静态节点”(如 <span>静态文本</span>)和“静态根节点”(包含多个

静态节点的父节点),运行时 diff 时会直接跳过这些节点的对比(因为其内容和属性不会变化),

• React:

• 对比粒度是「Fiber 任务单元」:将整个 diff 过程拆分为多个独立的任务单元(每个 Fiber 节点对

应一个任务单元),执行过程中可被高优先级任务中断(如用户输入、动画),待高优先级任务完成后恢复对比。

• 优势:避免长时间占用主线程,保障用户交互流畅;劣势:中断与恢复过程需要保存/读取任务状

态,存在少量调度开销。

• Vue:

• 对比粒度是「节点层级」:diff 过程为同步一次性完成,无中断机制(Vue3 虽支持调度器,但仅用

于异步组件、nextTick 等场景,不影响 diff 核心流程)。

• 优势:无调度开销,对比过程更高效;劣势:若组件树层级过深、节点过多,可能阻塞主线程,导

致页面卡顿(需通过拆分组件、懒加载等手动优化)。

4. 适用场景差异总结

• React Diff:更适合“复杂组件树+频繁用户交互”场景(如企业级后台、移动端应用),通过可中

断调度保障交互流畅,牺牲少量 diff 效率换取更好的用户体验。

• Vue Diff:更适合“中等复杂度组件树+频繁列表更新”场景(如电商列表、数据可视化页面),通

过编译优化和精准移动优化,实现更高的 diff 效率和 DOM 更新性能。

三十七、React18 引入了哪些重要的新特性?简单介绍一下

React18 的核心升级方向是「并发渲染(Concurrent Rendering)」,通过重构底层架构(如调度器、协调器),引入一系列新特性和 API,旨在提升应用的响应速度和用户体验,同时保持对旧版本的

向下兼容。核心新特性可分为“底层架构升级”“核心 API 新增/优化”“开发体验优化”三大类:

1. 底层架构核心升级:并发渲染(Concurrent Rendering)

这是 React18 最核心的升级,并非新增 API,而是底层协调引擎的能力增强。并发渲染允许 React 中断、暂停、恢复或放弃渲染任务,优先处理高优先级任务(如用户输入、动画),避免低优先级任务

(如数据加载、列表渲染)阻塞主线程,从而保障页面交互流畅。

关键说明:并发渲染默认不开启,需通过新的根节点渲染 API(createRoot)启用(旧版 render API 仍兼容,但无法使用并发特性)。

2. 核心 API 新增与优化

(1)新的根节点渲染 API:createRoot

4 5// 新版(React18)

6const root = ReactDOM.createRoot(document.getElementById('root'));

7root.render(<App />);

优势:启用并发渲染、支持自动批处理、简化服务端渲染逻辑。

(2)自动批处理(Automatic Batching)

升级了旧版的“批量更新”机制,将批量更新的范围扩展到所有场景(包括原生事件、setTimeout、 Promise 回调等),默认合并多个 setState 调用为一次渲染,减少 DOM 操作次数,提升性能(旧版

仅在 React 合成事件、生命周期中支持批量更新)。

示例:

Code block

1

2// React18前:setTimeout中不支持批量更新,会触发2次渲染
3setTimeout(() => {
4setState({ count: 1 });
5setState({ name: 'xxx' });
6}, 0);

7

8// React18后:自动批处理,仅触发1次渲染
9setTimeout(() => {
10setState({ count: 1 });
11setState({ name: 'xxx' });
12}, 0);

若需强制同步更新,可使用 ReactDOM.flushSync 包裹。

(3)过渡更新(Transitions):startTransition

用于标记“低优先级更新”(如列表筛选、搜索结果渲染),告知 React 此类更新可被高优先级任务(如用户输入)中断,避免因低优先级更新导致页面卡顿。

核心价值:区分“紧急更新”(如输入框输入)和“非紧急更新”(如输入后的搜索结果渲染),保障紧急更新的响应速度。

示例:

全站分卷索引 · 28 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷
  20. 20第 20 卷
  21. 21第 21 卷
  22. 22第 22 卷
  23. 23第 23 卷
  24. 24第 24 卷
  25. 25第 25 卷
  26. 26第 26 卷
  27. 27第 27 卷
  28. 28第 28 卷