Vue中组件透传子组件属性至useAttrs的Volar类型校验方案
解决MySelect组件传递子组件属性的Volar类型报错问题
核心思路
要实现「向MySelect传入MyButton的合法属性时Volar不报错,同时这些属性进入useAttrs()而非MySelect的props」,关键是通过类型扩展告知Volar组件支持的额外属性,但不将这些属性定义为MySelect自身的props。
具体实现方案
方案1:类型扩展声明组件可接受的属性
在MySelect组件中,直接为useAttrs添加类型注解,包含MyButton的props类型,同时定义自身独立的props:
<script setup lang="ts"> import MyButton from './MyButton.vue' import type { MyButtonProps } from './MyButton.vue' // 声明组件可接受的额外属性(来自MyButton的props) type AcceptableAttrs = MyButtonProps // 获取所有传入的属性,类型包含MyButton的props const attrs = useAttrs<AcceptableAttrs>() // 定义MySelect自身的props,与按钮属性完全分离 const props = defineProps<{ placeholder?: string modelValue?: string }>() // 必须关闭属性自动继承,避免属性绑定到根div defineOptions({ inheritAttrs: false }) </script> <template> <div class="my-select"> <MyButton v-bind="attrs" /> <!-- 组件其他内容 --> </div> </template>
如果需要全局所有组件都能接受MyButton的属性(可选),可以在项目的类型文件中扩展Vue的全局类型:
// src/types/vue.d.ts import type { ComponentCustomProps } from 'vue' import type { MyButtonProps } from '@/components/MyButton.vue' declare module 'vue' { interface ComponentCustomProps extends MyButtonProps {} }
方案2:排除自身props的精确类型控制
如果MySelect的部分props和MyButton的props重名,需要明确排除自身已定义的props,确保传给按钮的属性不包含组件自身props:
<script setup lang="ts"> import MyButton from './MyButton.vue' import type { MyButtonProps } from './MyButton.vue' // 定义MySelect自身的props const props = defineProps<{ size?: string // 假设MySelect自己也有size属性,需要排除在按钮attrs之外 placeholder?: string }>() // 从MyButtonProps中排除MySelect自身已定义的props,得到按钮可接受的属性类型 type ButtonAttrs = Omit<MyButtonProps, keyof typeof props> const attrs = useAttrs<ButtonAttrs>() defineOptions({ inheritAttrs: false }) </script> <template> <div class="my-select"> <MyButton v-bind="attrs" /> <!-- 组件其他内容 --> </div> </template>
关键提示
- 必须设置
inheritAttrs: false,否则Vue会自动将未定义为props的属性绑定到组件的根元素(这里是.my-select的div),而不是传给MyButton。 - 上述方案仅做类型检查,不会将MyButton的props转化为MySelect的props,所有额外属性依然保留在
useAttrs()中,完全符合需求。
内容的提问来源于stack exchange,提问作者stackoverfloweth
相关产品推荐
相关产品推荐

