vue3的动态指令参数实现动态插槽
1.背景
目前在做一个很常见的业务组件,大概就是将一个表格组件,分页组件、表格筛选form组件组合成一个大的通用组件,在业务组件使用中,通过传入一份schema进行驱动,所有组件通信处理好之后,发现如何动态使用具名插槽
2.使用场景
2.1 基础运用
// a.vue
<slot name="a">
// b.vue
<template #a>xxxx</template>
2.2 目前场景
//业务组件
<template #a>xxx</template>
<slot name="a"></slot>
单独使用表格组件与业务组件插槽我们可以正常使用,但是目前引用了组合式组件中,我们需要先使用具名插槽,同时再将插槽输出
// 组合通用业务组件中, 类似于这样, 但是这样显然是不对的,我们需要将它作为一个变量使用
<template #a>
<slot name="a"></slot>
</template>
2.3 解决
首先我们需要获取到业务中所有插槽,然后进行过滤掉不需要的,进行遍历之后再渲染
// 获取插槽数
const slots = useSlots()
const slotWrite = ['tableAction']
/**
* @description 支持外部插槽绑定,过滤默认插槽tableAction、tableTool
*/
const slotList = Object.keys(slots).filter((item) => {
return !slotWrite.includes(item)
})
动态指令参数 这里的 #[slotname] 等同v-slot:[slotname]
// 使用动态指令参数方式
<template #[slotname]="data" v-for="(slotname, index) in slotList" :key="index">
<slot :name="slotname" :data="data"></slot>
</template>
3.tsx中的一些插槽用法
export const base: FunctionalComponent = (props, { slots }) => (
<div class={s.wrapper}>
{' '}
<div class={s.card}>
{' '}
{slots.imgs?.()} {slots.title?.()}{' '}
</div>{' '}
<div class={s.describe}>{slots.des?.()}</div>{' '}
</div>
)
export const PageOne = {
setup() {
return () => (
<Base>
{{
imgs: () => <img src={pig} class={s.icon} />,
title: () => <h2> title </h2>,
des: () => <>
<p> 描述信息1。。。。。</p>
<p> 描述信息2。。。。。</p>
</>
}}
</Base>
);
},
};