⚡ 30 秒速记
- 核心判断:虚拟节点是对界面结构的描述,渲染器通过挂载与更新把声明式描述映射为宿主环境操作
- 原理主线:围绕 「用 VNode 描述真实 DOM」、「用 VNode 描述抽象内容」、「VNode 的种类」 建立输入、状态变化与输出之间的因果关系
- 文章范围:系统讲解了Vue中VNode(虚拟DOM节点)的设计原理,包括如何用VNode描述真实DOM结构、属性、事件和子节点,以及VNode设计对渲染性能和框架架构的影响,帮助开发者深入理解Vue底层渲染机制。
- 边界与代价:
key、节点类型和稳定序列决定复用边界;虚拟 DOM 解决可预测更新,不保证永远比手写 DOM 快 - 工程落地:性能分析要看实际提交次数、节点移动和组件边界,不能只用“减少 DOM 操作”解释
VNode 本质上是对元素、组件、文本及 Fragment、Portal 等界面内容的结构化描述,渲染器再把它转换成真实宿主操作。 不同节点需要的字段不同,例如元素保存标签和子节点,组件引用组件本身,Portal 还要记录渲染目标。创建时用位标识记录节点类别,可以让挂载和更新阶段直接分派处理逻辑,减少反复猜测类型。这里的双端 Diff 等内容主要对应 Vue 2;新项目应以 Vue 3 的渲染器实现为基线。
这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。
版本校准: 本文出现 Object.defineProperty、Dep、Watcher 和双端 Diff 时,主要描述 Vue 2 实现;Vue 3 使用 Proxy、effect 与新的渲染器路径。Vue 2 已于 2023-12-31 结束维护,新项目应以 Vue 3 为基线,旧项目参考 Vue 2 EOL 官方说明 制定迁移与安全策略。
上一章讲述了组件的本质,知道了一个组件的产出是 VNode,渲染器(Renderer)的渲染目标也是 VNode。可见 VNode 在框架设计的整个环节中都非常重要,甚至设计 VNode 本身就是在设计框架,VNode 的设计还会对后续算法的性能产生影响。本章我们就着手对 VNode 进行一定的设计,尝试用 VNode 描述各类渲染内容。
# 用 VNode 描述真实 DOM
一个 html 标签有它的名字、属性、事件、样式、子节点等诸多信息,这些内容都需要在 VNode 中体现,我们可以用如下对象来描述一个红色背景的正方形 div 元素:
const elementVNode = {
tag: 'div',
data: {
style: {
width: '100px',
height: '100px',
backgroundColor: 'red'
}
}
}