全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 8 分钟 ✍️ juanwangdev

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 } }
)

第一个参数不能为 nullundefined,必须是有效的标签名、组件或返回组件的函数。

第二个参数:数据对象

数据对象定义节点的属性、样式、类、事件等。这是最复杂的参数。

完整字段清单

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',  // 仅用于动态组件
})

注意事项

attrsdomProps 互斥:同一字段不应同时出现在两者中。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>
  )
}

要点总结

  • 第一个参数:标签名(字符串)、组件(选项/名称)或异步组件函数
  • 第二个参数:数据对象,包含 propsattrsdomPropsstyleclassondirectives
  • 第三个参数:子节点,可以是文本字符串或扁平的 VNode 数组
  • attrs 设置 HTML 特性,domProps 设置 DOM 属性,二者互斥
  • 事件名使用小写(如 click),不使用驼峰
  • 子节点不能是嵌套数组,需扁平化处理

存放路径:articles/VUE/进阶/自定义指令与渲染函数/createElement参数.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 高阶组件
下一篇 → 指令参数与修饰符
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库