参考: https://cn.vuejs.org

作用: 创建虚拟 DOM 节点 (vnode).

hyperscript 的简称——意思是“能生成 HTML (超文本标记语言) 的 JavaScript”.

参数说明:

// 完整参数签名
function h(
  type: string | Component,
  props?: object | null,
  children?: Children | Slot | Slots
): VNode

// 省略 props
function h(type: string | Component, children?: Children | Slot): VNode

type Children = string | number | boolean | VNode | null | Children[]

type Slot = () => Children

type Slots = { [name: string]: Slot }
  • 第一个参数: 既可以是一个字符串 (用于原生元素) 也可以是一个 Vue 组件定义

  • 第二个参数: 传递的 prop ( 可省略 )

  • 第三个参数: 子节点

当创建一个组件的 vnode 时,子节点必须以插槽函数进行传递。如果组件只有默认槽,可以使用单个插槽函数进行传递。否则,必须以插槽函数的对象形式来传递。

为了方便阅读,当子节点不是插槽对象时,可以省略 prop 参数。

示例:

创建原生元素
import { h } from 'vue'

// 除了 type 外,其他参数都是可选的
h('div')
h('div', { id: 'foo' })

// attribute 和 property 都可以用于 prop
// Vue 会自动选择正确的方式来分配它
h('div', { class: 'bar', innerHTML: 'hello' })

// class 与 style 可以像在模板中一样
// 用数组或对象的形式书写
h('div', { class: [foo, { bar }], style: { color: 'red' } })

// 事件监听器应以 onXxx 的形式书写
h('div', { onClick: () => {} })

// children 可以是一个字符串
h('div', { id: 'foo' }, 'hello')

// 没有 prop 时可以省略不写
h('div', 'hello')
h('div', [h('span', 'hello')])

// children 数组可以同时包含 vnode 和字符串
h('div', ['hello', h('span', 'hello')])

// 像 `.prop` 和 `.attr` 这样的的属性修饰符
// 可以分别通过 `.` 和 `^` 前缀来添加
h('div', { '.name': 'some-name', '^width': '100' })
创建组件
import Foo from './Foo.vue'

// 传递 prop
h(Foo, {
  // 等价于 some-prop="hello"
  someProp: 'hello',
  // 等价于 @update="() => {}"
  onUpdate: () => {}
})

// 传递单个默认插槽
h(Foo, () => 'default slot')

// 传递具名插槽
// 注意,需要使用 `null` 来避免
// 插槽对象被当作是 prop
h(MyComponent, null, {
  default: () => 'default slot',
  foo: () => h('div', 'foo'),
  bar: () => [h('span', 'one'), h('span', 'two')]
})
Slot插槽组合式拆分
  // 设置
  const reportingSlot = ({ row, rowIndex }) => {
    return h(resolveComponent('x-table-action'), { // 按名称手动解析已注册的组件
      row,
      rowIndex,
      onSave: () => handleSaveRow(row),
      onRemove: () => handleRemoveRow(row)
    })
  }

  export {
    reportingSlot 
  }
// 引用时需要用 component 
 <template #xxx_xxx="{ row, rowIndex }">
    <component :is="reportingSlot({ row, rowIndex })" />
 </template>

ps: 在使用jsx时拆分的情况类似