vue.js中处理多层级组件通信应优先使用$attrs和$listeners实现属性与事件的透传,避免层层props传递;$attrs收集未声明的属性,v-bind="$attrs"可转发,$listeners收集未处理的事件,v-on="$listeners"可转发;二者组合实现“穿透式”传递,适用于封装基础组件等局部高复用场景。

Vue.js 中处理多层级组件间属性传递,关键不是一层层写 props 和事件,而是用好 $attrs 和 $listeners 这两个内置机制。它们能跳过中间层,把未被显式声明的属性和事件直接透传下去,既干净又高效。
用 $attrs 透传未声明的属性
当父组件给子组件传了多个属性,但子组件只在 props 中定义了其中一部分,其余属性会自动收集到 this.$attrs 里。中间组件不需要逐个接收,只需用 v-bind="$attrs" 就能把所有未消费的属性“原样转发”给下一层。
- 适用于封装基础组件(如自定义 input、button)时透传原生 HTML 属性(
placeholder、disabled、class等) - 注意:
$attrs不包含已声明为 props 的属性,也不含class和style(它们默认会被挂载到根元素上) - 如果想合并透传的 class 或 style,需手动处理:
:class="[$attrs.class, localClass]"
用 $listeners 透传事件监听器
父组件绑定的自定义事件(如 @change、@click),若子组件没用 $emit 显式触发,也不会自动冒泡。但这些监听器会存入 this.$listeners,中间组件只需 v-on="$listeners" 即可一键转发。
- Vue 2.4+ 支持,Vue 3 中被
v-model和事件参数替代,但逻辑类似 - 配合
$attrs使用,就能实现“属性 + 事件”双通道透传 - 若需拦截或加工某个事件,可在中间组件中定义同名方法,再手动调用
this.$listeners.xxx()
组合使用实现“穿透式”传递
在 B、C 这类中间容器组件中,同时写 v-bind="$attrs" 和 v-on="$listeners",就能让 A 的属性和事件直达 D,中间层完全不感知数据内容。
- 示例写法:
<d v-bind="$attrs" v-on="$listeners"></d> - 该方式不破坏单向数据流,也不依赖全局状态,适合局部高复用场景
- 比
provide/inject更轻量,比EventBus更可控,比层层 props 更简洁
补充:何时该换其他方式?
透传不是万能解法。以下情况建议切换策略:
- 跨业务模块通信(如登录态、权限)→ 用
provide/inject或 Pinia/Vuex - 兄弟组件或非嵌套组件交互 → 用事件总线或状态管理
- 需要深度响应式控制或复杂校验逻辑 → 在中间层主动接收并处理,而非简单透传
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










