目录

vue3一文理解h函数的使用

vue3:一文理解h函数的使用


第一章 前言

以下是官方文档下对h函数的一些说明与使用:

在绝大多数情况下,Vue 推荐使用模板语法来创建应用。然而在某些使用场景下,我们真的需要用到 JavaScript 完全的编程能力。这时 渲染函数 就派上用场了。

小编在该篇文章中主要说明一下h函数使用的场景和如何使用!

第二章 h函数的使用

2.1 h函数语法

  • 1.type: 第一个参数既可以是一个字符串 (用于原生元素) 也可以是一个 Vue 组件
  • 2.props: 要传的参数,可以理解成<div class=“test” id=“test” @click=“handleClick” />标签上所有的属性都可以写在props里面,但是如果是事件监听器需要以 onXxx 的形式书写
  • 3.children: 子节点,可以是字符串,也可以是数组包含多个节点,也可以是对象针对于组件的插槽
  • 注意: h函数必须只有一个根节点,如果需要一次性渲染多个组件,需要在children中实现
import { h } from 'vue'

// 完整参数
/*
    1.type: 第一个参数既可以是一个字符串 (用于原生元素) 也可以是一个 Vue 组件
    2.props: 要传的参数,可以理解成<div class="test" id="test" @click="handleClick" />标签上所有的属性都可以写在props里面,但是如果是事件监听器需要以 onXxx 的形式书写
    3.children: 子节点,可以是字符串,也可以是数组包含多个节点,也可以是对象针对于组件的插槽
*/
const VNod = h(
  type: string | Component,
  props?: object | null,
  children?: Children | Slot | Slots
)

2.2 原生标签渲染

import { h } from 'vue'

// const vnode1 = h(
//     'div', // type
//     { id: 'foo', class: 'bar' }, // props
//     [] || '' // children
// )


const message = ref('这是一个h函数渲染的div')
const vnode2 = h(
  'div',
  {
    class: 'div-test',
    style: {
      color: 'red'
    },
    onclick: ()=> {
      console.log('点击输出');
    }
  },
  message.value
)

const vnode3 = h('div')
……

2.3 组件渲染

// DownOutlined是antd的图标组件
h(DownOutlined, { style: { 'font-size': '12px' } })

2.4  渲染多个标签/组件

// h函数必须只有一个根节点,如果需要一次性渲染多个组件,需要在children中实现
h(
  'div',
  {
    class: 'w-full gap-x-3 flex items-center justify-start'
  },
  [
    h('span', null)
    h('span', null, record.seqNumber)
  ]
)

2.5 slot插槽渲染

// 这是antd的Tooltip, default为默认插槽
h(Tooltip, { title: str }, { default: () => showStr })
// 自定义组件HelloWorld,default为默认插槽,header为具名插槽
h(
    HelloWorld, 
    { 
        msg: message.value,
        onClick: (value)=> {
            console.log(value);
        },
    },
    {
        default: ()=> h('div', '我是 HelloWorld 组件的默认插槽里面的值'),
        header: ()=> h('div', '我是 HelloWorld 组件的 header 插槽里面的值'),
    }
)

2.6 例子

以下只是小编在实战中使用的一段代码:

// 利用一段三目运算活用
// 小编这里之所以props传null是因为不传会报错,但是官网说明是可选的,具体看大家敲代码时的具体情况了
return !isSub
  ? h(
      'div',
      {
        class: 'w-full gap-x-3 flex items-center justify-start'
      },
      [
        record.childList.length
          ? expandedRowsSet.value.has(record.id)
            ? h(CaretDownOutlined, {
                onClick: () => removeExpanedRow(record.id)
              })
            : h(CaretRightOutlined, {
                onClick: () => addExpanedRow(record.id)
              })
          : h('span', null),
        h('span', null, record.seqNumber)
      ]
    )
  : h('span', null)