组件传递泛型(vue3.3+)
官方提供了函数签名,但实际使用非常不方便,仍然需要手动声明运行时的 props(虽然官方计划提供一个 Babel 插件,自动推断并注入运行时 props ,以便省略运行时 props 的声明,截至目前还没有提供),不如直接用defineComponent定义组件
const Comp = defineComponent(
<T extends string | number>(props: { msg: T; list: T[] }) => {
// 就像在 <script setup> 中一样使用组合式 API
const count = ref(0)
return () => {
// 渲染函数或 JSX
return <div>{count.value}</div>
}
},
// 目前仍然需要手动声明运行时的 props
{
props: ['msg', 'list']
}
)
但是直接用defineComponent定义组件的话,组件之间如何传递泛型就是一个非常头疼的问题,总不能在父组件在子组件emits的方法中再声明一次返回体类型,这样很繁琐,我们希望的是,使用子组件时,只需声明一次需要支持的泛型类型即可,这里可以使用函数封装一下
export default function defineGenericComponent<T>() {
return defineComponent(...) //defineComponent是实际子组件内容
}
下面用一个实际的例子来说明
// Parent.tsx
import { defineComponent, ref, Ref, onMounted } from 'vue'
import Child from './Child'
interface DataItem {
name: string
}
const ChildCom = Child<DataItem>()
export default defineComponent({
setup() {
onMounted(() => {
console.log('onMounted') //生命周期
})
return () => (
<ChildCom
onSelectionChange={(res) => {
console.log(res)
}}
/>
)
},
})
// Child.tsx
import { defineComponent, onMounted } from 'vue'
export default function defineGenericComponent<T>() {
//defineComponent是实际子组件内容
return defineComponent({
props: {
data: {
type: Array as PropType<T[]>,
default: () => [],
},
},
emits: {
selectionChange: (val: T[]) => true,
},
setup(props, { emit }) {
onMounted(() => {
console.log('onMounted') //生命周期
})
return () => (
<div
onClick={() => {
emit('selectionChange', props.data)
}}
>
child
</div>
)
},
})
}
通过如上方式引用子组件后,父组件在使用Child组件时,就有emit方法的提示,且能正常显示onSelectionChange的返回体类型声明

Web前端(W3Cways.com) - Web前端学习之路
评论前必须登录!
注册