$attrs适用于组件仅作中转、不消费属性而需透传至子组件的场景;通过defineOptions({ inheritAttrs: false })关闭默认继承,并在目标元素上使用v-bind="$attrs"即可实现原样透传,支持事件与v-model自动拆解。

直接用 $attrs 配合 v-bind="$attrs",再根据需要关掉默认继承,就能让中间组件不写 props、不手动解构,把父级传来的未声明属性原样透传下去。
什么时候该用 $attrs?
当一个组件只是“中转站”,不消费某个属性(比如 data-test、size、theme),但又要把它传给内部子组件时,就适合用 $attrs。
- 父组件传了
@change、disabled、class,但子组件自己不用,只负责交给内部的<input> - 封装第三方组件(如
<el-input></el-input>)时,想支持所有原生属性,又不想一一声明 props - 多层嵌套 A → B → C → D,A 要把
id和@focus传到最内层 D,B 和 C 不关心具体值
基础用法:自动继承 + 手动绑定
默认情况下,未在 defineProps 中声明的属性会自动加到组件的根元素上。如果根元素就是你要承载这些属性的目标(比如组件模板只有一个 <button></button>),那什么都不用做。
但如果根元素是容器类标签(如 <div>),而你想把属性透传给内部的 <code><input> 或 <select></select>,就得手动绑定:
- 在
<script setup></script>中加defineOptions({ inheritAttrs: false }) - 在模板里,把
v-bind="$attrs"写在真正要接收属性的那个元素上,例如:<input v-bind="$attrs"> - 注意:事件监听器(如
@click)也会进$attrs,所以v-bind="$attrs"同时透传属性和事件
配合 v-model 更省事
$attrs 天然包含 v-model 拆解后的 modelValue 和 @update:modelValue,不需要额外处理就能透传双向绑定。
- 父组件写:
<myinput v-model="value" size="large"></myinput> - MyInput 组件内只需在
<input v-bind="$attrs">上绑定,value、@input、@change全部自动生效 - 即使内部用的是
<textarea></textarea>或自定义控件,行为也和原生一致
多根节点或复杂结构要注意
如果组件有多个根节点(比如同时有 <label></label> 和 <input>),Vue 不会自动决定把 $attrs 挂到哪个节点上,必须显式绑定。
- 不绑定会报运行时警告
- 可以只给某个节点绑定:
<input v-bind="$attrs">,其他节点保持干净 - 访问带短横线的属性要用方括号,比如
$attrs['data-id'],不能用点语法

















