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...

相关推荐
大明8810 分钟前
Vue 中导致 detached 元素产生的常见行为
前端·vue.js
哎呦你好19 分钟前
CSS 渐变完全指南:从基础概念到实战案例(线性渐变/径向渐变/重复渐变)
前端·css
hachi031321 分钟前
el-table-column如何获取行数据的值
javascript·vue.js·elementui
工呈士28 分钟前
React进阶:状态管理选择题
前端·react.js·面试
一壶纱28 分钟前
箭头函数
前端·javascript
curdcv_po28 分钟前
Error: Electron failed to install correctly, please delete node_modules/electron
前端
鸿蒙预备高级程序员29 分钟前
HarmonyOS5 鸿蒙沉浸式工具类封装~~
前端
susnm30 分钟前
Dioxus 介绍 [翻译]
前端·rust
荣江30 分钟前
Svelte 5 状态管理全解析:从响应式核心到项目实战
前端
spionbo31 分钟前
Vue 开发中动态添加 HTML 元素的方法与实践
前端·javascript