$attrs 是 Vue 3 组件属性透传的核心机制,自动收集未声明的属性与事件监听器并响应式透传;单根组件默认继承,多根或需定向透传时须设 inheritAttrs: false 并 v-bind="$attrs";需配合 useAttrs()、computed 控制优先级及插槽、defineExpose 构建完整封装链。

$attrs 是 Vue 3 中实现组件属性透传的核心机制,它自动收集父组件传入、但未被 defineProps 显式声明的所有属性与事件监听器(如 class、style 除外),并支持响应式透传到目标元素或子组件。它不是“可选技巧”,而是封装高复用、低侵入 UI 组件的基础设施。
单根组件的默认继承行为
当子组件只有一个根元素,且未设置 inheritAttrs: false 时,Vue 会自动将未声明的属性(如 id、data-test、@click)挂载到该根元素上:
- 父组件写:
<MyInput size="large" @change="onInputChange" /> - 若
MyInput.vue根节点是<input>,且未声明size和change,则最终渲染为:<input size="large" @change="onInputChange"> -
class和style会被智能合并——父传的 class 不覆盖子组件模板中已有的 class,而是并入
多根/非根元素透传:必须显式绑定
当组件使用多个根节点(fragments)、根是容器标签(如 <div>),或需把属性透传给内部深层元素(如封装了 <el-input> 的表单控件)时,必须关闭默认继承并手动绑定:
- 在
<script setup>中调用:defineOptions({ inheritAttrs: false }) - 在模板中明确指定接收位置:
<input v-bind="$attrs" />或<el-input v-bind="$attrs" /> - 注意:驼峰命名事件(如
@update:modelValue)在$attrs中以onUpdate:modelValue形式存在,v-bind="$attrs"可原生支持v-model透传
安全透传:避免属性覆盖与优先级失控
直接 v-bind="$attrs" 简单,但可能覆盖组件内部设定的固定值。例如父组件传 size="small",而组件逻辑默认应为 "medium",此时需控制优先级:
立即学习“前端免费学习笔记(深入)”;
- 使用
useAttrs()获取响应式$attrs对象 - 通过
computed合并本地逻辑与透传值:size: attrs.size ?? 'medium' - 对第三方组件封装尤其关键:避免父组件意外覆盖关键 props(如
disabled、modelValue)
与插槽、exposed 协同构建完整封装链
$attrs 解决“输入”透传,还需配合其他机制形成闭环:
- 插槽内容由
$slots透传,与$attrs并行使用,实现结构+行为双透传 - 若需暴露子组件方法(如
focus()、validate()),需用defineExpose主动导出,不能依赖$attrs - 组合式 API 中,
$attrs不再通过this.$attrs访问,统一使用useAttrs()(Vue 3.3+ 推荐)


















