vue3的动态指令参数你用过了吗?

208 阅读1分钟

vue3的动态指令参数实现动态插槽

1.背景

目前在做一个很常见的业务组件,大概就是将一个表格组件,分页组件、表格筛选form组件组合成一个大的通用组件,在业务组件使用中,通过传入一份schema进行驱动,所有组件通信处理好之后,发现如何动态使用具名插槽

image.png

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>
    );
  },
};