Vue组件通讯$attrs/$listeners
$attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (
class和style除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class和style除外),并且可以通过v-bind="$attrs"传入内部组件——在创建高级别的组件时非常有用。
一句话总结:接收除了 props 声明外的所有绑定属性(class、style 除外)
图解
由于 child.vue 在 props 中声明了 name 属性,$attrs 中只有 age、gender 两个属性,输出结果为:
{ age: “20”, gender: “man” }
另外可以在 grandson.vue 上通过 v-bind="$attrs", 可以将属性继续向下传递,让 grandson.vue 也能访问到父组件的属性,这在传递多个属性时会显得很便捷,而不用一条条的进行绑定。
如果想要添加其他属性,可继续绑定属性。但要注意的是,继续绑定的属性和 $attrs 中的属性有重复时,继续绑定的属性优先级会更高。
$listeners
包含了父作用域中的 (不含
.native修饰器的)v-on事件监听器。它可以通过v-on="$listeners"传入内部组件——在创建更高层次的组件时非常有用。
一句话总结:接收除了带有 .native 事件修饰符的所有事件监听器
App.vue 中对 child.vue 绑定了两个事件,带有 .native 的 click 事件和一个自定义事件,所以在 child.vue 中,输出 $listeners 的结果为:
{ customEvent: fn }
同 attrs 属性一样,可以通过 v-on="$listeners",将事件监听器继续向下传递,让 grandson.vue 访问到事件,且可以使用 $emit 触发 App.vue 的函数。
如果想要添加其他事件监听器,可继续绑定事件。但要注意的是,继续绑定的事件和 $listeners 中的事件有重复时,不会被覆盖。当 grandson.vue 触发 customEvent 时,child.vue 和 parent.vue 的事件都会被触发,触发顺序类似于冒泡,先到 child.vue 再到 parent.vue。
DEMO
https://codesandbox.io/s/eloquent-wood-b2zed
应用
当我们去二次封装别人组件时,可能别人组件上有很多属性,我们不想再次重写一遍
这时候就可以使用 v-bind="$attrs" 和 v-on="$listeners" 。这是 vue 2.4 版本提供
vm.$attrs 是一个属性,其包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。这些未识别的属性可以通过 v-bind="$attrs" 传入内部组件。未识别的事件可通过 v-on=”$listeners”传入。
举个例子,比如我创建了我的按钮组件 myButton,封装了 element-ui 的 el-button 组件(其实什么事情都没做),在使用组件 <my-button /> 时,就可以直接在组件上使用 el-button 的属性,不被 prop 识别的属性会传入到 el-button 元素上去:
1 | <template> |