vue vnode实现
Vue VNode 实现原理
VNode(虚拟节点)是 Vue 中用于描述真实 DOM 的轻量级 JavaScript 对象。通过 VNode,Vue 可以在内存中构建虚拟 DOM 树,高效地进行 diff 算法比较,最终最小化真实 DOM 操作。
VNode 的基本结构
VNode 的核心属性包括标签名、数据、子节点等。以下是一个简化的 VNode 结构示例:
class VNode {
constructor(tag, data, children, text, elm) {
this.tag = tag; // 标签名,如 'div'
this.data = data; // 节点数据,如 attributes、props、events
this.children = children; // 子节点数组
this.text = text; // 文本内容(文本节点)
this.elm = elm; // 对应的真实 DOM 节点
this.key = data?.key; // 节点的 key,用于 diff 优化
}
}
创建 VNode
Vue 通过 createElement 函数(通常缩写为 h)创建 VNode。例如:

// 创建一个 div 元素的 VNode
const vnode = h('div', { class: 'container' }, [
h('span', { style: { color: 'red' } }, 'Hello'),
' World'
]);
VNode 的类型
VNode 可以分为多种类型,常见的有:
- 元素节点:带有标签名的普通节点(如
div、span)。 - 文本节点:仅包含文本内容的节点。
- 组件节点:对应 Vue 组件的 VNode。
- 注释节点:用于模板中的注释内容。
- 克隆节点:用于优化静态节点或插槽内容。
VNode 的渲染流程
VNode 的渲染分为以下几个阶段:

- 生成 VNode 树:通过模板编译或
render函数生成 VNode 树。 - Patch 阶段:通过
patch函数将 VNode 转换为真实 DOM。 - Diff 算法:在更新时比较新旧 VNode,仅更新变化的部分。
Diff 算法优化
Vue 的 diff 算法基于以下策略:
- 同层比较:仅比较同一层级的节点,不跨层级比较。
- key 的作用:通过
key标识节点身份,避免不必要的重新渲染。 - 双端比较:在子节点列表比较时,采用头尾指针优化查找效率。
示例代码:简单 VNode 渲染
以下是一个简化的 VNode 渲染示例:
function createElement(tag, data, children) {
return new VNode(tag, data, children);
}
function render(vnode, container) {
const el = document.createElement(vnode.tag);
for (const key in vnode.data) {
el.setAttribute(key, vnode.data[key]);
}
if (vnode.children) {
vnode.children.forEach(child => {
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
render(child, el);
}
});
}
container.appendChild(el);
}
const vnode = createElement('div', { id: 'app' }, [
createElement('h1', {}, 'Hello VNode'),
'This is a text node'
]);
render(vnode, document.body);
组件 VNode 的处理
对于组件 VNode,Vue 会执行以下步骤:
- 创建组件实例。
- 执行组件的
render函数生成子 VNode。 - 递归处理子 VNode 直至全部转换为真实 DOM。
通过 VNode 的抽象,Vue 实现了高效的 DOM 更新机制,避免了直接操作真实 DOM 的性能开销。






