vue 3 自定义表单组件支持原生属性透传,关键在于 $attrs 与 inheritattrs: false 配合:单根组件自动透传 class、style、placeholder 等及 @input 等事件;多根或定向绑定时需禁用默认继承并显式 v-bind="$attrs";v-model 展开项不进 $attrs,其余事件仍可透传;推荐 useattrs() + 组合式封装提升可控性与类型安全。

Vue 3 中自定义表单组件支持原生属性透传,核心在于正确利用 $attrs 和 inheritAttrs: false 的配合,让父组件传入的 placeholder、disabled、required、autofocus 等原生 input 属性,以及 @input、@change、@blur 等事件监听器,自动落到内部真实 DOM 元素(如 <input> 或第三方封装组件)上。
单根组件可直接依赖默认透传
如果你的自定义表单组件只渲染一个根元素(例如直接包裹一个 <input>),且没有显式声明所有原生属性为 props,Vue 3 会自动把未声明的属性和事件绑定到该根元素:
- class、style 会与根元素已有的值合并(不是覆盖)
- id、name、placeholder、readonly、disabled 等原生属性直接透传
- 以
onXxx命名的事件(如onInput)或@input写法,也会透传并触发对应 DOM 事件
多根或需定向透传时必须禁用默认继承
当组件结构含多个根节点(如带 label + input + error 提示),或你想把透传属性绑定到非根元素(比如内部的 <input> 而不是外层 <div>),就必须主动关闭默认行为:
<ul>
<li>在 <code><script setup></script> 中调用 defineOptions({ inheritAttrs: false })(Vue 3.3+)
inheritAttrs: false
v-bind="$attrs" 显式绑定到目标元素,例如:<input v-bind="$attrs">
与 v-model 协同时注意事件优先级
使用 v-model 时,v-bind="$attrs" 仍有效,但要注意:
-
v-model默认展开为:modelValue+@update:modelValue,这两项不属于$attrs(已被识别为 prop/emits) - 其他原生事件(如
@focus、@keydown.enter)仍保留在$attrs中,可被透传 - 若内部用的是第三方组件(如
<uni-easyinput></uni-easyinput>),确保它自身也支持透传;否则需手动解构$attrs并逐个绑定
实际封装建议:兼顾简洁与可控
推荐在封装表单控件时采用组合式写法,清晰分离职责:
- 用
useAttrs()替代直接访问$attrs,更语义化且兼容 TypeScript 类型推导 - 对特殊属性(如
class、style)可单独处理,避免全量v-bind="$attrs"导致样式冲突 - 若需拦截或转换某些属性(如把
clearable转为内部逻辑),可在computed中基于$attrs衍生新对象再绑定











