Vue3 script setup中自定义Input组件如何透传继承原生input属性
自定义Input组件继承原生属性实现方案
问题场景
需要实现一个带label的自定义Input组件,要求组件能接收所有原生input支持的HTML属性并绑定到内部input标签上,初始待修正代码如下:
<script setup lang="ts"> import { defineProps, InputHTMLAttributes } from "vue"; interface Props extends InputHTMLAttributes { label?: string; } defineProps<Props>(); </script>
<template> <div> <span v-show="label">{label}</span> <input {?????} /> </div> </template>
当前代码存在两个核心问题:一是模板插值语法错误,二是未配置原生属性透传逻辑,无法将父组件传入的原生属性绑定到内部input上。
修正步骤
- 第一步:关闭根节点默认属性透传
Vue3默认会把父组件传入、且未在props/emits中声明的属性、事件绑定到组件根节点(也就是当前代码的外层div),需要手动关闭该行为,在script中添加配置:defineOptions({ inheritAttrs: false }) - 第二步:修正模板基础语法
Vue模板插值需要使用双大括号,label文本的正确写法为{{ props.label }},需要用变量接收defineProps的返回值才能在模板中获取自定义prop。 - 第三步:绑定透传属性到内部input
Vue提供内置的$attrs对象,自动存储所有父组件传入的非自定义props属性、原生事件,直接用v-bind="$attrs"绑定到input标签即可,不需要逐个声明所有原生属性。
完整可运行代码
<script setup lang="ts"> import { defineProps, InputHTMLAttributes } from "vue"; // 关闭根节点自动属性透传 defineOptions({ inheritAttrs: false }) interface Props extends InputHTMLAttributes { label?: string; // 如果要支持v-model双向绑定,放开下面这行 // modelValue?: string | number } const props = defineProps<Props>(); // 如果要支持v-model双向绑定,放开下面这段 // const emit = defineEmits<{ // 'update:modelValue': [value: string] // }>() </script> <template> <div> <span v-show="props.label">{{ props.label }}</span> <input v-bind="$attrs" <!-- 如果要支持v-model双向绑定,放开下面两行 --> <!-- :value="props.modelValue" @input="emit('update:modelValue', ($event.target as HTMLInputElement).value)" --> /> </div> </template>
补充说明
- 该写法会自动透传所有原生input支持的属性(例如
type、placeholder、disabled、maxlength)和事件(例如@focus、@blur、@change),不需要重复在Props接口中声明。 - 如果需要给原生属性设置默认值,直接写在input标签上即可,父组件传入的同名属性会自动覆盖默认值,例如
<input v-bind="$attrs" type="text" />,父组件传入type="password"时会自动切换为密码输入框。
内容的提问来源于stack exchange,提问作者Lívia Belizário
相关产品推荐
相关产品推荐

