Vue没有脏检查机制,它采用基于数据劫持与依赖追踪的响应式系统实现精准更新:通过getter/setter或Proxy拦截属性访问与修改,自动建立数据与视图的映射关系,变化时仅触发相关组件更新,无需全局比对快照。

Vue 并不使用“脏检查”机制,它采用的是基于响应式系统触发的“精准更新”机制。所谓“脏检查”,是 AngularJS 的核心设计——通过定时快照比对来发现变化;而 Vue 从设计之初就摒弃了这种低效方式,转而依靠数据劫持(Vue 2 用 Object.defineProperty,Vue 3 用 Proxy)实现属性级的变更感知。
Vue 没有脏检查,只有依赖追踪
当一个数据被模板引用时,Vue 在读取该属性(getter)阶段自动将其与当前正在执行的渲染 watcher 建立联系,这个过程叫“依赖收集”。后续一旦该属性被修改(setter),就会立刻通知对应 watcher,触发更新。整个过程不依赖轮询、不扫描全量数据、不比对快照——它是精确到具体字段的响应链路。
- 例如:
{{ user.name }}渲染时,会触发user.name的 getter,从而把当前组件的 watcher 记录进name属性对应的依赖列表中 - 之后执行
user.name = 'Alice',setter 立即通知该 watcher,而不是等下一轮“扫描”才发现变化 - 如果
user.age完全没在模板里出现,它的 setter 就不会触发任何更新,也不会被纳入响应系统
精准更新靠的是最小化重渲染
当响应式数据变动引发 re-render,Vue 并不是直接操作真实 DOM,而是生成新的虚拟节点(vnode),再通过 diff 算法对比新旧 vnode 树,只更新真正发生变化的节点及其子树。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 静态节点(
v-once或编译时标记为 static)在 diff 阶段被跳过,不参与比对 - 列表渲染中使用
key,让 Vue 能识别元素身份,避免无谓的移动或重建 - 组件级更新默认是独立的:父组件更新不会导致子组件无条件重 render,除非其 props 确实变化
异步批处理进一步优化粒度
即便多个响应式数据在一次同步代码中被修改,Vue 也会将所有相关 watcher 收集起来,在下一个 tick 统一执行更新——这就是 nextTick 的作用。
立即学习“前端免费学习笔记(深入)”;
- 比如连续赋值
a = 1; b = 2; c = 3;,只会触发一次 patch,而非三次 - 这既避免了重复 DOM 操作,也防止中间状态被短暂渲染出来
- 开发者可通过
this.$nextTick()或await nextTick()获取 DOM 更新后的时机
为什么有人误以为 Vue 用了脏检查?
混淆常来自两个方面:一是术语泛化,把“检测变化并更新视图”的广义行为都叫“脏检查”;二是 Vue 的 watch 和 computed 支持深度监听(deep: true),此时内部确实会对嵌套对象做递归遍历——但这属于显式配置的监听策略,并非框架默认的全局脏检查机制。
- 默认的响应式更新永远是路径明确、按需触发的
- 深度 watch 是可选的、开销可控的补充能力,不是渲染主流程
- Vue 3 的
reactive对 Proxy 的利用,甚至能自然支持 Map/Set/Date 等原生类型,进一步强化了精准性

















