【Vue3】 h()函数的用法

目录

介绍

参数

使用案例

[1.创建虚拟 DOM 元素](#1.创建虚拟 DOM 元素)

[2. 组件的动态渲染](#2. 组件的动态渲染)

[3. 创建功能组件](#3. 创建功能组件)

4.渲染动态属性

[5. 使用插槽](#5. 使用插槽)

[6. 创建动态标签](#6. 创建动态标签)


介绍

h() 函数用于辅助创建虚拟 DOM 节点,它是 hypescript 的简称------能生成 HTML (超文本标记语言) 的 JavaScript,它有另外一个名称,叫做 createVnode()。在 Vue 项目中使用 HTML 标签构建页面时,最终结果会转化为 vnode,而该h()函数直接创建 vnode,可以更灵活地构建组件渲染逻辑,并提高性能。

参数

  • type:要创建的节点类型,可以是 HTML 标签、组件或函数(功能组件)。
  • props(可选):包含节点属性的对象,作为 prop 传递。
  • children(可选):子节点可以是字符串、数组或其他 vnode 对象。
  1. type: HTML标签名:如果有type字符串,则会被解析为HTML标签。
    Component:如果type是对象或者函数,则会被解析为Vue组件。
    异步组件:type也可以是一个返回Promise的函数,该Promise将被解析到组件。
  2. props:Props 是可选参数,用于指定节点的属性。
    传递 props 时,传递一个包含属性名称和值的对象作为 prop。
    您也可以将null其作为 props 的值传递。
  3. children:子节点可以是字符串,数组或其他 vnode 对象。
    如果子节点是一个数组,则数组中的每个元素都将被视为节点的子节点。
    如果子节点是一个函数,它将在渲染期间被调用,并且其返回值将作为子节点。

注意事项:

  • 如果没有props,那么通常可以将children作为第二个参数传入;
  • 如果会产生歧义,可以将null作为第二个参数传入,将children作为第三个参数传

官方完整类型参数

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 }

使用案例

1.创建虚拟 DOM 元素

h函数可以在两个地方使用:

  • render函数选项中;
  • setup函数选项中(setup本身需要是一个函数类型,函数再返回h函数创建的VNode);
javascript 复制代码
import { h } from 'vue'

export default {
  render() {
    return h('div', { className: 'app' }, [
      h('h2', { className: 'title' }, 'I am title'),
      h('p', null, 'I am content')
    ])
  }
}
// 或者
import { defineComponent } from "vue";
export default defineComponent({
  name: "Jsx",
  render() {
    return I am div;
  },
});

定义一个setup返回渲染函数的函数。

javascript 复制代码
import { h } from "vue"

export default {
  setup() {
    // setup is a function that returns another function
    return () => h("div", { class: "app" }, [
      h("h2", { class: "title" }, "I am title"),
      h("p", null, "I am content")
    ])
  }
}

2. 组件的动态渲染

javascript 复制代码
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

const nowComponent = ref('ComponentA');

function changeComponent() {
  nowComponent.value = nowComponent.value === 'ComponentA' ? 'ComponentB' : 'ComponentA';
}

const createComponent = () => {
  return h(nowComponent.value === 'ComponentA' ? ComponentA : ComponentB);
};

3. 创建功能组件

javascript 复制代码
import { h, defineEmits } from 'vue';

const FunctionalComponent = (props, context) => {
  return h('div', null, [
    h('p', null, props.text),
    h('button', { onClick: context.emit.bind(context, 'click') }, 'click')
  ]);
};

const emit = defineEmits(['click']);

function handleClick() {
  console.log('handleClick');
}

如上所示,这是一个典型的函数式组件使用方法,包括如何在父子组件中与它们交互。FunctionalComponent 接收 props 和 context 参数,并使用 h() 函数构造页面。此外,它还通过触发父组件中的事件处理程序context.emit。

4.渲染动态属性

javascript 复制代码
  import { ref } from 'vue';

  const visible = ref(true);

  function myVisibility() {
    visible.value = !visible.value;
  }

  const componentWithProps = () => {
    return h('div', { class: { visible: visible.value } }, 'div');
  };

如上所示,里面的函数根据 h()的值判断 vnode 是否带有class ,并在点击按钮时实现动态样式。当然,动态 class 只是一个例子,实际上里面的各种属性或者子组件都可以动态灵活

5. 使用插槽

javascript 复制代码
import { h } from 'vue';

const SlotComponent = (props, context) => {
  return h('div', null, [
    h('p', null, 'In slot:'),
    context.slots.default && context.slots.default()
  ]);
};

如上所示,在引用SlotComponent组件时,其内部标签内的内容将作为默认插槽的内容传递给SlotComponent。此外,还可以使用context.slots.default()来获取并渲染默认插槽的内容。因此,当我们封装一个函数式组件,但内部有动态部分时,特别适合以这种方式使用插槽。

6. 创建动态标签

javascript 复制代码
import { ref } from 'vue';

const tag = ref('div');

function changeTag() {
  tag.value = tag.value === 'div' ? 'section' : 'div';
}

const createElement = () => {
  return h(tag.value, null, 'dynamic');
};

这种方式避免了使用v-if产生大量冗余代码。

相关推荐
To_OC7 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
To_OC7 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic7 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy8 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志8 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble9 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长9 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯10 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜11 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司11 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能