createElement参数
createElement(通常简写为 h)是渲染函数的核心,理解其参数类型和约束是正确使用渲染函数的前提。
函数签名
JavaScript
// @returns {VNode}
createElement(
// {String | Object | Function}
// HTML 标签名、组件选项或解析组件的函数
'div',
// {Object}
// 数据对象,定义节点的属性、样式、事件等
{ /* 可选 */ },
// {String | Array}
// 子节点,文本字符串或 VNode 数组
[ /* 可选 */ ]
)
第一个参数:节点类型
第一个参数决定创建什么类型的虚拟节点。
HTML 标签
传入标签名字符串,创建普通元素。
JavaScript
h('div')
h('span')
h('p')
组件
传入组件选项对象或已注册的组件名称。
JavaScript
import MyComponent from './MyComponent.vue'
// 使用组件选项
h(MyComponent)
// 使用已注册的组件名
h('my-component')
// 异步组件
h(() => import('./AsyncComponent.vue'))
动态组件
JavaScript
h(
this.componentName, // 动态决定组件
{ props: { data: this.data } }
)
第一个参数不能为
null或undefined,必须是有效的标签名、组件或返回组件的函数。
第二个参数:数据对象
数据对象定义节点的属性、样式、类、事件等。这是最复杂的参数。
完整字段清单
JavaScript
h('div', {
// === 组件相关 ===
props: {
// 组件 props
myProp: 'value'
},
// === HTML 特性 ===
attrs: {
// 普通 HTML 特性(如 id、name)
id: 'my-id',
'data-foo': 'bar'
},
// === DOM 属性 ===
domProps: {
// 直接设置 DOM 属性
value: 'input value',
innerHTML: '<span>HTML</span>'
},
// === 样式 ===
style: {
// 内联样式(与 v-bind:style 相同)
color: 'red',
fontSize: '14px',
backgroundColor: '#fff'
},
// === CSS 类 ===
class: {
// 类名映射(与 v-bind:class 对象语法相同)
active: true,
disabled: false
},
// 或数组语法
class: ['active', 'container'],
// === 事件 ===
on: {
// Vue 事件监听(与 v-on 相同)
click: this.handleClick,
change: this.handleChange
},
nativeOn: {
// 原生 DOM 事件(仅对组件有意义)
click: this.nativeClick
},
// === 指令 ===
directives: [
{
name: 'loading',
value: this.isLoading,
expression: 'isLoading',
arg: 'spinner',
modifiers: { large: true }
}
],
// === 组件插槽 ===
scopedSlots: {
default: (props) => h('span', props.text)
},
// === 其他 ===
key: 'unique-key', // 用于 Diff 算法
ref: 'myRef', // 引用标识
slot: 'header', // 插槽名称(在父组件中使用)
name: 'component-name', // 仅用于动态组件
})
注意事项
attrs和domProps互斥:同一字段不应同时出现在两者中。attrs设置 HTML 特性,domProps设置 DOM 属性。
事件名使用小写:
on: { click: fn },而非onClick。
第三个参数:子节点
子节点可以是文本字符串、VNode 数组或返回 VNode 的函数。
文本字符串
JavaScript
h('div', {}, '简单文本内容')
VNode 数组
JavaScript
h('div', {}, [
h('span', '第一个子元素'),
h('span', '第二个子元素'),
'文本节点'
])
动态子节点
JavaScript
h('ul', {}, this.items.map(item =>
h('li', { key: item.id }, item.name)
))
子节点必须是扁平的 VNode 数组,不能嵌套数组。使用
Array.flat()处理嵌套。
JavaScript
// 错误:嵌套数组
h('div', {}, [
[h('span'), h('span')] // 不允许
])
// 正确:扁平化
h('div', {}, [
h('span'),
h('span')
])
特殊场景
函数式组件
函数式组件直接返回 VNode,无状态无实例。
JavaScript
Vue.component('smart-list', {
functional: true,
props: { items: Array },
render(h, context) {
const { props } = context
if (props.items.length > 0) {
return h('ul', props.items.map(item => h('li', item)))
}
return h('p', '空列表')
}
})
函数式组件的
render接收(h, context)两个参数,无this。
使用 JSX
项目配置支持 JSX 时,可简化渲染函数写法。
JavaScript
// JSX 等价于上面的 h() 调用
render() {
return (
<div class="container">
<h1>{this.title}</h1>
{this.items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</div>
)
}
要点总结
- 第一个参数:标签名(字符串)、组件(选项/名称)或异步组件函数
- 第二个参数:数据对象,包含
props、attrs、domProps、style、class、on、directives等 - 第三个参数:子节点,可以是文本字符串或扁平的 VNode 数组
attrs设置 HTML 特性,domProps设置 DOM 属性,二者互斥- 事件名使用小写(如
click),不使用驼峰 - 子节点不能是嵌套数组,需扁平化处理
存放路径:articles/VUE/进阶/自定义指令与渲染函数/createElement参数.md
📝 发现内容有误?点击此处直接编辑