Vue3 里的 h 函数的运用场景!

大家好,我是 前端架构师 - 大卫

更多优质内容请关注微信公众号 @程序员大卫

初心为助前端人🚀,进阶路上共星辰✨,

您的点赞👍与关注❤️,是我笔耕不辍的灯💡。

背景

上一篇文章我们讲了 h 函数到底是什么,以及它的基本用法。这一篇将继续深入,介绍 h 函数在实际开发中的几种典型运用场景。

三种运用场景

1. 二次组件的封装

假设我们在 App.vue 中调用 HelloWorld 组件,并传递了插槽:

html 复制代码
<!-- App.vue -->
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
</script>

<template>
	<HelloWorld>
		<template #header>
			<div>Header</div>
		</template>
		<div>Main</div>
		<template #footer>
			<div>Footer</div>
		</template>
	</HelloWorld>
</template>

HelloWorld.vue 组件如下:

html 复制代码
<!-- HelloWorld.vue -->
<template>
	<div>
		<slot name="header"></slot>
		<slot></slot>
		<slot name="footer"></slot>
	</div>
</template>

页面最终渲染内容为:

css 复制代码
Header
Main
Footer

现在如果我们想对 HelloWorld 进行二次封装,可以创建一个 Child.vue 组件:

html 复制代码
<!-- Child.vue -->
<script setup lang="ts">
import HelloWorld from "./HelloWorld.vue";
</script>

<template>
	<div>
		<h1>Child</h1>
		<HelloWorld v-bind="$attrs">
			<template v-for="(_, slot) in $slots" #[slot]="slotProps">
				<slot :name="slot" v-bind="slotProps"></slot>
			</template>
		</HelloWorld>
	</div>
</template>

此时我们在 App.vue 中改为调用 Child.vue

html 复制代码
<!-- App.vue -->
<script setup lang="ts">
import Child from "./components/Child.vue";
</script>

<template>
	<Child>
		<template #header>
			<div>Header</div>
		</template>
		<div>Main</div>
		<template #footer>
			<div>Footer</div>
		</template>
	</Child>
</template>

最终页面渲染:

css 复制代码
Child
Header
Main
Footer

这种方式虽然可以实现插槽透传,但写法略显繁琐。我们可以使用 <component> 动态组件结合 h 函数简化写法:

html 复制代码
<!-- Child.vue -->
<script setup lang="ts">
import { h } from "vue";
import HelloWorld from "./HelloWorld.vue";
</script>

<template>
	<div>
		<h1>Child</h1>
		<component :is="h(HelloWorld, $attrs, $slots)"></component>
	</div>
</template>

2. 命令式地显示弹框

假如我们项目中使用了 ant-design-vue 组件库,展示弹框通常是这样的:

html 复制代码
<!-- App.vue -->
<template>
	<a-button type="primary" @click="showModal">Open Modal</a-button>
	<a-modal v-model:open="open" title="Basic Modal" @ok="handleOk">
		<p>Some contents...</p>
	</a-modal>
</template>

<script lang="ts" setup>
import { ref } from "vue";
const open = ref(false);

const showModal = () => {
	open.value = true;
};

const handleOk = () => {
	open.value = false;
};
</script>

我们可以通过 h 函数来命令式地展示弹框:

html 复制代码
<!-- App.vue -->
<template>
	<a-button type="primary" @click="showModal">Open Modal</a-button>
</template>

<script lang="ts" setup>
import { Modal } from "ant-design-vue";
import { createApp, h } from "vue";

const showModal = () => {
	const modal = () =>
		h(
			Modal,
			{
				title: "Basic Modal",
				open: true,
				onOk: () => unmount(),
				onCancel: () => unmount(),
			},
			() => h("p", "Some contents...")
		);

	const div = document.createElement("div");
	document.body.appendChild(div);

	const app = createApp(modal);
	app.mount(div);

	const unmount = () => {
		app.unmount();
		document.body.removeChild(div);
	};
};
</script>

⚠️ 这种方式的小问题是:弹框关闭时不会有动画过渡效果。

3. 表格中动态渲染内容

在使用 ant-design-vue 渲染表格时,基础代码如下:

html 复制代码
<template>
	<a-table :columns="columns" :data-source="data" bordered></a-table>
</template>

<script lang="ts" setup>
const columns = [
	{
		title: "Name",
		dataIndex: "name",
	},
	{
		title: "Address",
		dataIndex: "address",
	},
];

const data = [
	{ name: "John Brown", address: "New York No. 1 Lake Park" },
	{ name: "Jim Green", address: "London No. 1 Lake Park" },
	{ name: "Joe Black", address: "Sidney No. 1 Lake Park" },
];
</script>

如果我们希望为"名字"加上超链接,可以通过插槽实现:

html 复制代码
<template>
	<a-table :columns="columns" :data-source="data" bordered>
		<template #bodyCell="{ column, text }">
			<template v-if="column.dataIndex === 'name'">
				<a href="#">{{ text }}</a>
			</template>
		</template>
	</a-table>
</template>

<script lang="ts" setup>
// columns 和 data 同上
</script>

还可以通过 customRender 配合 h 函数实现更灵活的渲染逻辑:

html 复制代码
<template>
	<a-table :columns="columns" :data-source="data" bordered></a-table>
</template>

<script lang="ts" setup>
import { h } from "vue";

const columns = [
	{
		title: "Name",
		dataIndex: "name",
		customRender: ({ text }: { text: string }) => {
			return h("a", { href: "#" }, text);
		},
	},
	{
		title: "Address",
		dataIndex: "address",
	},
];

// data 同上
</script>

如果内容更复杂,也可以使用 tsx 写法进一步提升可读性和可维护性。

总结

通过这篇文章我们可以看到,h 函数在 Vue 3 中非常强大,适用于:

  • 插槽透传时简化代码;
  • 实现命令式弹框;
  • 动态渲染表格内容等高级场景。

掌握 h 函数的使用,有助于我们编写更灵活、更底层、更可控的 Vue 组件逻辑。

参考

www.bilibili.com/video/BV1Zm...

相关推荐
阿珊和她的猫27 分钟前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
加班是不可能的,除非双倍日工资5 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi5 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip6 小时前
vite和webpack打包结构控制
前端·javascript
excel6 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国6 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼6 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy6 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
草梅友仁6 小时前
草梅 Auth 1.4.0 发布与 ESLint v9 更新 | 2025 年第 33 周草梅周报
vue.js·github·nuxt.js
ZXT7 小时前
promise & async await总结
前端