我在 vue 3 (3.5.8) typescript 项目中有一个选项卡组件。这些选项卡接受一个名为
nav
的道具,它可能看起来像这样:
const nav = ref([
{
id: 'about',
name: 'About',
},
{
id: 'enquire',
name: 'Enquire',
},
])
对于每个导航项,我们都会生成一个
slot
,其中包含简单的内容顺序命名系统。
<div v-if="nav" class="tabs-content">
<div
v-for="(tab, index) in nav"
:id="tab.id"
:key="index"
<slot :name="`tab${index + 1}`"></slot>
</div>
</div>
给我们 tab1 和 tab2 插槽。这意味着我们可以像这样填充选项卡内容:
<template #tab1></template>
但是在运行构建命令时,vue-tsc 抛出错误:
错误 TS2339:类型“TabsSlots”上不存在属性“tab1”。
vue 文档有一个关于此的部分,但不是很深入: https://vuejs.org/api/sfc-script-setup.html#defineslots 我对此的所有尝试均不成功。
我已确保 typescript、vue、vue-tsc 包都是最新的
到目前为止,我的所有方法都是尝试根据 nav 属性注册动态插槽,这与创建插槽本身的方式相同。
有人有办法解决这个问题吗?我在 StackOverflow 上找不到有关此特定问题的任何内容,并且 AI 工具似乎正在努力解决 DefineSlots 作为一项新功能的问题。
尝试使用通用 Tab[] 类型并将其用于 props 和 slot。不要忘记将
as const
添加到 nav
:
<script lang="ts" setup generic="const Tabs extends Readonly<Tab[]>">
import { ref } from 'vue'
export interface Tab {
id: string
name: string
}
const selected = ref('about')
const $slots = defineSlots<{
[K in Exclude<Exclude<keyof Tabs | `${Tabs['length']}`, keyof []>, '0'> as `tab${K & string}`]: () => void
}>();
const props = withDefaults(
defineProps<{
nav?: Tabs
}>(),
{
nav: undefined,
}
)
</script>