组件通信之 $attrs 和 $listeners
# $attrs
# 介绍
官方解释:
包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
简单来说:
包含了所有父组件在子组件上设置的属性(除了prop传递的属性、class 和 style )。
# 图解
例一:
下图中,在parent.vue中给子组件child.vue设置了name、age、gender三个属性。因为子组件child.vue通过props声明了name属性,所以this.$attrs最后输出{ age: "20", gender: "man" }。

例二:
另外可以在grandson.vue 上通过 v-bind="$attrs", 将属性继续向下传递,让 grandson.vue也能访问到父组件的属性,这在传递多个属性时会显得很便捷,而不用一条条的进行绑定。
如果想要添加其他属性,可继续绑定属性。但要注意的是,继续绑定的属性和$attrs中的属性有重复时,继续绑定的属性优先级会更高。

# $listeners
# 介绍
官方解释:
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
我的理解:
接收除了带有.native事件修饰符的所有事件监听器
# 图解
例一:
parent.vue中对child.vue绑定了两个事件,带有.native的click事件和一个自定义事件,所以在 child.vue 中,输出$listeners的结果为:
{ customEvent: fn }

例二:

同 $attrs 属性一样,可以通过v-on="$listeners",将事件监听器继续向下传递,让grandson.vue 访问到事件,且可以使用$emit 触发 parent.vue的函数。
如果想要添加其他事件监听器,可继续绑定事件。但要注意的是,继续绑定的事件和 $listeners中的事件有重复时,不会被覆盖。当 grandson.vue 触发 customEvent 时,child.vue 和 parent.vue的事件都会被触发,触发顺序类似于冒泡,先到 child.vue 再到 parent.vue。