Vue中如何扩展原生HTML元素的Prop类型定义?
实现方案
这个需求完全可以实现,我们可以分开运行时属性声明和TypeScript类型推导两部分处理,也可以直接用Vue3内置的透传属性机制简化实现。
方案1:最简透传实现(无需显式声明原生属性)
Vue3 本身内置了 Attributes 透传机制,没有显式声明在props中的原生属性会自动作为透传属性存在,直接绑定到内部的input元素即可,不需要额外写工具函数:
<!-- 单文件组件示例 --> <template> <input v-bind="$attrs" /> </template> <script> export default defineComponent({ props: { // 只需要声明自定义属性即可 additionalProp: String } }) </script>
如果是 TypeScript 项目需要获得原生input属性的类型提示,直接扩展官方导出的原生属性接口即可:
import { defineComponent } from 'vue' import type { InputHTMLAttributes } from 'vue' interface Props extends InputHTMLAttributes { additionalProp?: string } export default defineComponent<Props>({ props: { additionalProp: String } })
如果用<script setup>语法,写法更简洁:
<script setup lang="ts"> import type { InputHTMLAttributes } from 'vue' interface Props extends InputHTMLAttributes { additionalProp?: string } const props = defineProps<Props>() </script> <template> <input v-bind="props" /> </template>
方案2:显式展开原生props的实现
如果你确实需要把所有原生input的属性显式声明到组件的props对象中,可以自己实现一个工具函数完成你期望的写法:
第一步:实现工具函数
// utils/props-helper.js import { inputProps, buttonProps /* 按需引入其他原生标签的props定义 */ } from '@vue/runtime-dom' const nativePropsMap = { input: inputProps, button: buttonProps } export function getComponentProps(tag) { return nativePropsMap[tag] || {} }
第二步:组件中使用
import { defineComponent } from 'vue' import { getComponentProps } from './utils/props-helper' export default defineComponent({ props: { ...getComponentProps('input'), additionalProp: String }, setup(props) { // 这里可以直接访问所有原生input属性和自定义的additionalProp } })
TypeScript类型适配
如果是TS项目,给工具函数加上类型定义即可获得完整的类型提示:
import type { ComponentProps, DefineComponent } from 'vue' import { inputProps } from '@vue/runtime-dom' export function getComponentProps<T extends keyof HTMLElementTagNameMap>(tag: T): ComponentProps<DefineComponent<typeof inputProps>> export function getComponentProps<T extends object>(component: T): ComponentProps<T> export function getComponentProps(tagOrComponent: any) { // 运行时实现和上文一致 }
内容的提问来源于stack exchange,提问作者light24bulbs
相关产品推荐
相关产品推荐

