vue更新dom属性采用patch props机制,只更新真正变化的属性:普通属性用setattribute/removeattribute;布尔属性按js值处理;style深度比对仅改变动项;class智能合并复用classlist;事件监听器缓存并精准替换;避免全量设置引发重排。

Vue 更新 DOM 属性不是靠重新渲染整个元素,而是通过 Patch Props 机制,在比对新旧虚拟节点(vnode)时,**只更新真正变化的属性**,跳过未变项,避免冗余操作。
Props 更新的核心逻辑
当组件重渲染生成新 vnode 后,Vue 会进入 patch 流程。若新旧 vnode 的标签名和关键标识(如 key)一致,且是同一类型节点,就会执行 props 补丁(patchProps)——即逐个检查 props 对象中的属性,按类别精细化处理:
-
普通 HTML 属性:比如
id、class、src,直接用el.setAttribute()或el.removeAttribute()同步;值为空或undefined时自动移除。 -
布尔属性:如
disabled、checked,依据 JS 布尔值决定是否调用el.toggleAttribute()或el.setAttribute(),不依赖字符串值。 -
样式(style):深度比对对象结构,仅增删/修改变化的 CSS 属性,不全量覆盖
el.style.cssText;支持驼峰写法(fontSize)与短横线写法(font-size)自动转换。 -
类名(class):区分对象形式(
{ active: true })、数组形式(['a', 'b'])和字符串,智能合并与切换,复用el.classListAPI,避免字符串拼接。 -
事件监听器:老监听器被缓存(_vei 内部字段),新旧 handler 引用相同时跳过;不同则先移除旧的、再绑定新的,支持事件修饰符(如
@click.stop)的运行时解析。
为什么不用全量 setAttribute?
全量设置属性会触发浏览器强制重计算(reflow),尤其在 class 或 style 频繁变动时性能明显下降。Vue 的 patchProps 是“差分式”更新:
- 只对 从有到无、从无到有、值改变 的属性执行 DOM 操作;
- 忽略未出现在新 props 中但旧 props 里存在的属性(自动清理);
- 对 style/class 这类高频属性做了专门优化路径,绕过通用逻辑,提升命中率。
key 和静态提升的影响
带 key 的节点能确保 identity 稳定,使 Vue 更准确判断 props 是否应复用;而编译阶段的 静态提升(hoist static)会让常量属性(如 id="header")在渲染函数外只创建一次,后续 patch 时直接跳过比对——这部分 props 根本不参与运行时更新流程。
开发者可干预的边界
你无法直接控制 patchProps 的内部执行,但可通过以下方式影响其效率:
- 为列表项提供稳定、唯一的
key,避免因 key 错误导致 props 全量重设; - 避免在模板中频繁拼接 class/style 字符串(如
:class="'a ' + (active ? 'b' : '')),改用对象或数组语法,便于深度 diff; - 自定义指令中若需手动操作 DOM 属性,应尽量复用已有的 prop 更新逻辑(例如通过
v-bind传入),而非绕过响应式系统直改el.xxx。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











