$attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
父组件调用子组件时,传递除了使用prop接受的以外属性 (class 和 style 除外),都可以使用$attrs获取。
若要多层级组件使用 $attrs,则需要在中间子组件使用 v-bind="$attrs" ,才可以被访问,否则访问$attrs为空对象。
$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
与$attrs类似,是对父组件on事件监听但收集,中间子组件使用v-on="$listeners"可以向该组件内的子组件传递监听器。
在vue3.0中 $listeners被移除!!!
在 Vue 2 中,你可以使用 this.$attrs 和 this.$listeners 分别访问传递给组件的 attribute 和事件监听器。结合 inheritAttrs: false,开发者可以将这些 attribute 和监听器应用到其它元素,而不是根元素
在 Vue 3 的虚拟 DOM 中,事件监听器现在只是以 on 为前缀的 attribute,这样就成了 $attrs 对象的一部分,因此 $listeners 被移除了。
所以,在vue3中使用$attrs即可实现属性和事件监听器的传递。
HelloWorld.vue
<template>
<div>
<h1>Hello World</h1>
<Child :message="message" name='hello' v-on:test1="test1" v-on:test2='test2'></Child>
</div>
</template>
<script>
import Child from './child'
export default {
name: "HelloWorld",
components: {
Child,
},
data() {
return {
message: '父组件数据'
}
},
props: {
msg: String,
},
};
</script>
Child.vue
<template>
<div>
<h1>子组件</h1>
<p>
attrs的数据:{{$attrs}}
</p>
<button @click="clickHandle()">childClick</button>
<!-- <GrandChild v-bind="$attrs"></GrandChild> -->
<GrandChild></GrandChild>
</div>
</template>
<script>
import GrandChild from './GrandChild'
export default {
name: "Child",
components: {
GrandChild
},
mounted() {
console.log('子组件中的attrs:'+this.$attrs);
},
methods: {
clickHandle() {
this.$emit('test1');
}
}
};
</script>
GrandChild.vue
<template>
<div>
<h2>孙子组件</h2>
<p>
attrs的数据:{{$attrs}}
</p>
<button @click="clickHandle()">GrandChildClick</button>
</div>
</template>
<script>
export default {
name: 'GrandChild',
mounted() {
console.log('孙子组件中的attrs:'+this.$attrs);
},
methods: {
clickHandle() {
this.$emit('test2')
}
}
}
</script>
不使用v-bind="$attrs"
使用v-bind="$attrs"