【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产生大量冗余代码。

相关推荐
小曲曲1 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年7 小时前
react中useMemo的使用场景
前端·react.js·前端框架