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

相关推荐
速易达网络28 分钟前
RuoYi、Vue CLI 和 uni-app 结合构建跨端全家桶方案
javascript·vue.js·低代码
耶啵奶膘34 分钟前
uniapp+firstUI——上传视频组件fui-upload-video
前端·javascript·uni-app
视频砖家1 小时前
移动端Html5播放器按钮变小的问题解决方法
前端·javascript·viewport功能
lyj1689972 小时前
vue-i18n+vscode+vue 多语言使用
前端·vue.js·vscode
小白变怪兽3 小时前
一、react18+项目初始化(vite)
前端·react.js
ai小鬼头3 小时前
AIStarter如何快速部署Stable Diffusion?**新手也能轻松上手的AI绘图
前端·后端·github
墨菲安全4 小时前
NPM组件 betsson 等窃取主机敏感信息
前端·npm·node.js·软件供应链安全·主机信息窃取·npm组件投毒
GISer_Jing4 小时前
Monorepo+Pnpm+Turborepo
前端·javascript·ecmascript
天涯学馆4 小时前
前端开发也能用 WebAssembly?这些场景超实用!
前端·javascript·面试
我在北京coding5 小时前
TypeError: Cannot read properties of undefined (reading ‘queryComponents‘)
前端·javascript·vue.js