真实面经题目 · 原创解析

Virtual DOM 和真实 DOM 的区别是什么?

Virtual DOM 是用 JavaScript 对 UI 结构和状态结果做的一层描述;真实 DOM 是浏览器直接维护、参与样式计算、布局、绘制、事件和可访问性树等流程的节点对象。二者的关键区别在层级:Virtual DOM 让框架先在 JS 层计算 UI 变化、做 reconciliation 与调度,再把必要变更提交到真实 DOM。

出现于:阿里巴巴 · 前端

60 秒回答模板

真实 DOM 是浏览器提供的对象模型,修改它可能触发样式计算、布局、绘制和合成,频繁细粒度操作成本较高。Virtual DOM 是框架在 JS 内存中用普通对象或 Fiber 节点描述 UI 的结果,它不直接显示在页面上。React 会根据 state 或 props 的变化生成新的 UI 描述,与旧描述做 reconciliation,结合 key 判断节点能否复用,然后在提交阶段把必要变更批量应用到真实 DOM。它的价值不是保证每次都比真实 DOM 快,而是把直接 DOM 操作抽象成声明式 UI、集中更新、跨平台渲染和可调度的渲染流程。React Fiber 还把渲染阶段和提交阶段分开:渲染阶段可以计算、比较、暂停和恢复,提交阶段才会执行不可中断的真实 DOM 变更和副作用。

考点 定义边界
主线 真实 DOM 成本
易错点 把 Virtual DOM 说成真实 DOM 的完整复…

深入解析

01

定义边界

真实 DOM 是浏览器实现的文档对象模型,节点背后连接着样式系统、布局引擎、绘制管线、事件系统和可访问性相关结构。Virtual DOM 不是浏览器标准,也不是一个真正存在于页面里的节点树,而是框架用 JavaScript 数据结构描述某一时刻 UI 应该是什么样子。真实 DOM 是最终渲染目标,Virtual DOM 是框架内部的中间表示。

02

真实 DOM 成本

真实 DOM 操作的成本不只来自调用 API 本身,还来自它可能引发浏览器后续工作。写入 class、style、文本、属性或插入删除节点,可能让浏览器重新计算样式、重新布局、重新绘制,某些属性读取还可能迫使浏览器同步刷新布局信息。单次 DOM 改动未必慢,但大量分散、交错读写、无法合并的 DOM 操作会放大成本。

03

Virtual DOM 角色

Virtual DOM 的核心角色是把 UI 从“命令式地改哪个节点”转为“当前状态下界面应该是什么”。组件渲染函数根据状态返回一份 UI 描述,框架负责比较前后描述并决定如何更新真实宿主环境。它降低的是复杂 UI 的维护成本和一致性风险,不是简单地把所有 DOM 操作替换成更快的对象操作。

04

Diff 与 Reconciliation

状态变化后,框架会得到新的 UI 描述,并与上一次描述进行 reconciliation。React 的比较不是任意树的最优编辑距离算法,而是基于启发式假设:不同类型的元素通常对应不同子树,同层子节点通过 key 帮助判断身份。diff 的结果不是直接等于 DOM 更新,而是形成需要创建、移动、更新或删除的工作,再由后续流程提交到真实 DOM。

05

批量更新

Virtual DOM 配合框架调度可以把多次状态变化合并处理,避免每次状态写入都立刻触发真实 DOM 修改。批量更新的意义在于减少重复计算、统一处理优先级,并把最终必要变更集中提交。需要注意的是,批量不等于无成本:组件渲染、创建新描述、diff、执行生命周期或 Hook 逻辑都要消耗 JS 时间。

06

Key 的作用

key 不是为了让循环渲染不报提示,而是帮助框架在同一层级的兄弟节点之间识别稳定身份。没有稳定 key 时,插入、删除、排序可能导致框架错误复用节点或组件实例,出现输入框状态错位、动画异常、局部状态串位等问题。数组下标作为 key 在静态列表中问题不大,但在可重排、可删除列表中风险很高。

07

Fiber 与阶段边界

React Fiber 可以理解为更细粒度的内部工作单元结构,让渲染阶段的计算具备可拆分、可暂停、可恢复和按优先级调度的能力。React 更新大体分为渲染阶段和提交阶段:渲染阶段执行组件、计算新树、做比较并准备副作用列表,提交阶段才把变更应用到真实 DOM,并执行 ref 更新和 layout effect 等宿主环境相关操作。

08

性能取舍

Virtual DOM 不是永远更快的银弹。对于非常简单、明确且局部的更新,手写 DOM 或编译型框架可能生成更少运行时开销;对于大列表、频繁动画、复杂输入场景,Virtual DOM diff 本身也可能成为瓶颈。它更稳定的价值是以可接受运行时成本换取声明式编程模型、跨平台渲染能力、一致状态到 UI 映射和更强调度空间。

易错点

  • 把 Virtual DOM 说成真实 DOM 的完整复制品,忽略它只是 UI 描述和框架中间表示。
  • 绝对化地说 Virtual DOM 一定比真实 DOM 快,忽略运行时 diff 和组件渲染成本。
  • 只讲 diff,不讲提交到真实 DOM,回答没有覆盖完整更新路径。
  • 认为 key 只是消除列表渲染提示,忽略它决定稳定身份、实例复用和状态保留。
  • 把 Fiber 简单等同于 Virtual DOM,忽略 Fiber 更偏向工作单元和优先级调度。
  • 把 reconciliation 说成一定生成最少 DOM 操作,忽略 React 使用的是启发式比较。

面试官追问

Virtual DOM 为什么不直接等于性能优化?

因为它增加了创建 UI 描述、执行组件渲染、diff 和调度的 JS 成本。它能减少很多直接 DOM 操作的混乱和重复,但在简单局部更新、超高频动画或极大列表中,额外抽象也可能成为瓶颈。

React 的 diff 为什么需要 key?

同一层级的多个子节点如果类型相同,框架需要判断谁是谁。key 提供稳定身份,帮助框架在插入、删除、排序时复用正确的节点和组件实例。没有稳定 key 时,框架可能按位置复用,导致局部状态错位。

为什么不使用通用树编辑距离算法?

通用最优树 diff 对复杂 UI 来说成本过高,不适合作为每次交互更新的运行时基础。React 选择启发式策略,用不同类型通常重建、同层列表通过 key 判断身份,换取常见业务场景下可接受的比较成本。

Fiber 和 Virtual DOM 是什么关系?

Virtual DOM 更偏向描述 UI 结果,Fiber 更偏向 React 内部的工作单元和调度结构。Fiber 节点保存组件、props、state、更新队列、副作用标记、父子兄弟关系等信息,使渲染工作可以被拆分和按优先级处理。

真实 DOM 操作一定很慢吗?

不是。单次 DOM 操作通常并不可怕,问题常出在大量操作、读写交错、强制同步布局、重复布局和无批处理更新。Virtual DOM 的价值是让框架更容易组织更新,而不是证明每个 DOM API 调用都慢。