vue vnode实现
Vue VNode 实现原理
VNode(虚拟节点)是 Vue 中用于描述真实 DOM 的轻量级对象,它是 Vue 虚拟 DOM 的核心组成部分。VNode 的实现涉及以下几个关键方面:
VNode 的结构
VNode 是一个普通的 JavaScript 对象,包含描述 DOM 节点所需的各种属性。一个典型的 VNode 结构如下:
{
tag: 'div',
data: {
attrs: { id: 'app' },
class: 'container'
},
children: [
{ tag: 'span', text: 'Hello World' }
],
elm: null,
context: VueComponent,
key: undefined
}
tag:节点标签名data:节点属性、样式、事件等children:子节点数组elm:对应的真实 DOM 节点context:组件上下文key:节点的唯一标识
VNode 的创建
Vue 通过 createElement 函数(通常缩写为 h)创建 VNode。这个函数在编译模板或编写渲染函数时被调用:
// 渲染函数示例
render(h) {
return h('div', { id: 'app' }, [
h('span', 'Hello World')
])
}
VNode 的 diff 算法
当状态变化时,Vue 会创建新的 VNode 树,然后与旧的 VNode 树进行比较(diff),找出最小化的 DOM 操作:

- 同级比较:只比较同一层级的节点,不跨层级比较
- key 的作用:通过 key 可以复用相同 key 的节点
- 节点类型比较:如果节点类型不同,直接替换整个节点
- 属性比较:只更新变化的属性
VNode 的 patch 过程
diff 完成后,Vue 会执行 patch 操作将变化应用到真实 DOM:
function patch(oldVnode, vnode) {
if (sameVnode(oldVnode, vnode)) {
patchVnode(oldVnode, vnode)
} else {
const parent = oldVnode.elm.parentNode
createElm(vnode)
parent.insertBefore(vnode.elm, oldVnode.elm)
parent.removeChild(oldVnode.elm)
}
}
组件 VNode
对于组件,VNode 会有额外的属性:

{
tag: 'vue-component-1-my-component',
componentInstance: MyComponentInstance,
componentOptions: {
Ctor: MyComponent,
propsData: { /* props */ },
listeners: { /* events */ }
}
}
组件 VNode 在 patch 时会创建组件实例并挂载。
性能优化
VNode 的实现考虑了多种性能优化:
- 静态节点提升:编译时标记静态节点,在 patch 时跳过
- 事件缓存:避免每次渲染都创建新的事件对象
- SSR 优化:服务端渲染时复用 VNode
VNode 与响应式系统的关系
VNode 的创建和更新由 Vue 的响应式系统驱动。当响应式数据变化时,触发组件的重新渲染,生成新的 VNode 树,然后通过 diff 和 patch 更新 DOM。
这种设计使得 Vue 能够最小化 DOM 操作,提高性能,同时保持开发者的心智模型简单。






