虚拟 DOM 中的 props 是纯数据容器,不被解析,仅原样传递给 vnode;Vue 在 patch 阶段通过 class.js、style.js 等专项模块对 class、style 等特殊 props 进行归一化、合并与增量更新,以保障语义正确性和性能优化。

虚拟 DOM 中的 props 本身不被“解析”,而是作为普通 JavaScript 对象字段,原样传递给 vnode(虚拟节点对象)。真正起作用的是 Vue 在 patch 阶段对特定 props(如 class、style)做的专项处理——它们不是直接映射到 DOM 属性,而是被提取、归一化、合并后,再由模块(如 class.js、style.js)驱动真实 DOM 更新。
props 在 vnode 中的定位
vnode 的 props 字段(Vue 2 中叫 data,Vue 3 中统一为 props)是一个纯数据容器。例如:
`{ class: { active: true, 'text-error': false }, style: { color: 'red', fontSize: '14px' } }`
这个对象不会被“编译”或“解析”成其他结构,而是被保留下来,在后续更新时供平台特定模块读取和消费。
class 绑定的底层处理流程
Vue 在 web 平台注册了 class 模块(路径:vue/src/platforms/web/runtime/modules/class.js),其核心函数 updateClass 执行以下动作:
- 调用
genClassForVnode(vnode)合并静态 class(如模板中写的class="btn")与动态 class(:class绑定值),支持对象、数组、字符串混合写法 - 对过渡类(
_transitionClasses)做追加,确保动画类不被覆盖 - 对比新生成的 class 字符串与缓存的
el._prevClass,仅当变化时才执行el.setAttribute('class', ...)
style 绑定的底层处理逻辑
对应模块是 style.js,它接管 :style 的更新,关键行为包括:
- 将对象语法(如
{ color: val })转为合法 CSS 声明,自动补全浏览器前缀(如transform→webkitTransform) - 支持数组语法:依次遍历每个样式对象,深层合并同名属性,后者覆盖前者
- 对单位敏感属性(如
fontSize、margin)默认追加px,但会跳过已含单位或值为0、auto、initial等的字段 - 更新时只设置变更的样式键值,避免全量重写
el.style.cssText
为什么需要专门模块而不是通用 props 映射?
因为 class 和 style 是 DOM 中具有特殊语义和操作逻辑的属性:
-
class是空格分隔的字符串,需合并去重,不能简单赋值覆盖(否则丢失静态 class) -
style是内联样式集合,需逐条控制、单位推导、前缀注入,且修改单个属性不应影响其他样式 - 两者都涉及性能优化:比如 class 字符串比对、style 属性级 diff,避免无谓的 DOM 写入

















