⚡ 30 秒速记
- 核心判断:虚拟节点是对界面结构的描述,渲染器通过挂载与更新把声明式描述映射为宿主环境操作
- 原理主线:围绕 「基本原则」、「替换 VNode」、「更新标签元素」 建立输入、状态变化与输出之间的因果关系
- 文章范围:介绍了Vue渲染器中patch的原理和实现,包括新旧VNode的比对、DOM更新流程、核心patch逻辑及其在组件更新中的应用,帮助读者深入理解Vue高效渲染的底层机制。
- 边界与代价:
key、节点类型和稳定序列决定复用边界;虚拟 DOM 解决可预测更新,不保证永远比手写 DOM 快 - 工程落地:性能分析要看实际提交次数、节点移动和组件边界,不能只用“减少 DOM 操作”解释
patch 的作用是比较新旧 VNode,在保证结果正确的前提下尽量复用已有真实节点。 新旧节点类型不同就移除旧节点并挂载新节点;同为元素但 tag 不同也直接替换,因为继续比较没有实际意义。类型和标签一致时,新节点通过 nextVNode.el = prevVNode.el 复用 DOM,再更新 VNodeData 与子节点。像样式更新既要写入新增或变化的值,也要清掉新数据中已经不存在的旧值,这类逻辑适合统一收口到 patchData。
这篇文章不要按 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渲染成真实DOM的过程。渲染器除了将全新的VNode挂载成真实DOM之外,它的另外一个职责是负责对新旧VNode进行比对,并以合适的方式更新DOM,也就是我们常说的patch。本章内容除了让你了解基本的比对逻辑之外,还讲述了在新旧VNode比对的过程中应该遵守怎样的原则,让我们开始吧!
# 基本原则
通常重渲染(re-render)是由组件的更新开始的,因为在框架的使用层面开发者通过变更数据状态从而引起框架内部对UI的自动更新,但是组件的更新本质上还是对真实DOM的更新,或者说是对标签元素的更新,所以我们就优先来看一下如何更新一个标签元素。
我们首先回顾一下渲染器的代码,如下: