vue 3 中 vnode 不再是用户直接操作的核心对象,而是内部渲染系统的底层实现;通过 h() 函数声明式创建,结构更扁平、与 composition api 深度融合,官方推荐优先使用模板或 definecomponent。

VNode 在 Vue 3 中不再是用户直接操作的核心对象,而是内部渲染系统更底层的实现细节。它依然作为渲染函数(render)的返回值存在,但设计目标、创建方式和使用场景相比 Vue 2 有明显变化——不再鼓励手动构造复杂 VNode 树,而是通过组合式 API 和更语义化的工具(如 h())来声明式生成。
✅ VNode 的本质没变,但创建方式更简洁
Vue 3 中仍用 VNode 描述虚拟 DOM 节点,但不再暴露 VNode 构造函数给用户。取而代之的是统一的 h() 函数(即 “hyperscript”),它是创建 VNode 的标准入口:
-
h('div', { class: 'box' }, 'Hello')→ 返回一个 VNode -
h(MyComponent, { msg: 'hi' })→ 支持组件、原生标签、片段(Fragment)、文本节点等所有类型 -
h是响应式的:参数可为 ref、computed 或响应式对象,更新时自动触发重渲染
✅ 渲染函数更轻量,VNode 结构更扁平
Vue 3 的 VNode 对象字段大幅精简,去除了 Vue 2 中冗余的 componentOptions、context、functionalContext 等字段。关键属性聚焦于:
-
type:节点类型(字符串、组件、Fragment、Text等) -
props:标准化后的属性对象(含事件监听器以onXxx形式归一化) -
children:支持数组、字符串、null、其他 VNode,也支持slots函数(在 setup 渲染函数中可直接解构使用) -
key和ref仍为顶层字段,语义清晰,不嵌套在 props 中
✅ 与 Composition API 深度融合,逻辑复用更自然
在 setup() 中编写渲染函数时,VNode 不再是孤立的“树结构”,而是可被响应式逻辑驱动的表达结果:
- 可在
render()内直接使用ref、computed的值,无需h()外部预计算 - 插槽(slots)以函数形式注入,可按需调用并透传,支持动态 slot 名称和条件渲染
- 可通过
defineComponent+render快速封装无模板的逻辑型组件(如KeepAlive、Suspense的封装模式)
✅ 不再需要手写 VNode 工厂,生态转向高级抽象
Vue 3 官方推荐优先使用模板语法或 defineComponent 配合 setup,而非手动构建 VNode 树。真正需要显式使用 h() 的场景包括:
- 开发高阶组件(HOC)或渲染器插件
- 封装 JSX / TSX 支持(如
@vue/babel-plugin-jsx底层仍转为h()调用) - 服务端渲染(SSR)中定制 vnode 生成逻辑
- 测试渲染函数输出时断言 VNode 结构(配合
vue-test-utils)
本质上,Vue 3 把 VNode 从“用户可编程接口”降级为“框架契约载体”,把开发体验重心转移到响应式系统与组合式逻辑上。你仍会看到它、返回它、断言它,但不必理解它的全部字段,也不该试图 patch 它——那是 renderer 的事。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











