h函数是vue 3中创建虚拟dom节点(vnode)的核心工具,用于生成描述dom结构的轻量级javascript对象,不直接操作真实dom;它支持多参数重载,经标准化处理后返回含sel、data、children等字段的vnode对象,作为渲染器进行diff和patch的输入基础。

h 函数是构造虚拟 DOM 树的起点,它不操作真实 DOM,只返回描述结构的 JS 对象。整个流程从参数解析开始,到生成标准化 vnode 结束,核心在于统一结构、明确类型、递归组织子节点。
参数接收与重载识别
h 函数支持多种调用形式,需先判断传入参数的类型和数量:
- 一个参数:视为
sel(标签名或组件),props和children均为空 - 两个参数:第二个参数若为字符串/数字,视为
text;若为对象,视为props;若为数组或 vnode,则视为children - 三个参数:按顺序明确为
sel、props、children,这是最清晰、最推荐的用法
vnode 结构标准化构建
无论参数如何传入,最终都会归一为一个标准 vnode 对象,包含以下关键字段:
-
sel:字符串标签名(如'div')或组件引用 -
data:属性配置对象,含class、style、on事件等,Vue 中还支持props、attrs等细分字段 -
children:子节点数组,每个元素是 vnode 或字符串/数字文本;若传入单个 vnode,会自动包成数组 -
text:仅当子内容为纯文本且无子 vnode 时存在,优先级高于children -
elm和key:初始化时为undefined或用户显式指定,后续 patch 阶段才被赋值或使用
嵌套子节点的递归处理
当 children 是数组时,h 函数本身不递归执行,而是由上层调用者(如渲染函数)逐层调用 h 来生成子 vnode。例如:
h('ul', {}, [h('li', {}, '苹果'), h('li', {}, [h('span', {}, '红富士')])])
这种写法自然形成树形结构:顶层 ul 的 children 是两个 li vnode,第二个 li 的 children 又是一个 span vnode —— 整棵树靠多次 h 调用拼装,而非 h 内部递归。
与渲染器对接准备就绪
生成的 vnode 是纯数据对象,不含任何 DOM 操作逻辑。它直接交给渲染器(如 Vue 的 render 函数返回值,或 Snabbdom 的 patch 入口),后续由 diff 和 patch 流程决定如何映射为真实 DOM。此时 vnode 已完整携带层级、属性、内容、标识(key)等全部必要信息,构成可比对、可更新的虚拟 DOM 树根节点。










