一、需求场景描述
在封装组件时经常用到的就是 props和emit,但是当我们嵌套组件实在太多时候,一遍遍的使用这个组合就太繁琐了,而eventBus也被本人嫌弃(找代码太耗费时间),再就是vuex,但是vuex的体量又太大,为了封装组件传递几个属性,没太大必要。
v-bind="attrs"和v−on="listeners"就给我们带来惊喜。它们可以使得封装后的组件, “继承”原组件的几乎所有(class和style以及.native的事件除外) v-bind 属性和 v-on 事件,且用法和作用与在原组件一样。同样适用于封装第三方组件。
例如有个爷爷组件grandpa.vue,并且层级关系如下
<grandpa>
<father>
<son>
</son>
</father>
</grandpa>
然后在grandpa组件层级上传入一堆属性和方法
<template>
<div>
<grandpa name="tlb" :flag="true" :numbe="2" @isOpen="isOpen" @setData="setData"></grandpa>
</div>
</template>
<script>
import grandpa from ./grandpa.vue
export default {
components:{grandpa}
name: 'index',
data() {
return {
}
},
methods:{
isOpen(){
console.log(1)
},
setData(){
console.log(2)
}
}
}
</script>
<style scoped>
</style>
在father.vue 中只接收了name和flag属性,其他未接收的属性将作为下一级传递的参数,
<template>
<section>
<div class="mt-10">
<son v-bind="$attrs" v-on="$listeners" />
</div>
</section>
</template>
<script>
import son from './son';
export default {
components: {
son
},
props: {
name: {
type: String,
default: 'default'
},
flag: {
type: Boolean,
default: 'false'
}
}
};
</script>
在son.vue组件中我们只接收了number属性,但是这个属性是其父组件father使用 v-bind="$attrs" 从grandpa组件接收到的,father组件本身并没有使用props接收这个属性,但是son组件中的属性确可是使用
<template>
<section>
<div>
<!--在$attrs里面只会有props没有注册的属性
number属性已经被接收,此处不会显示值-->
{{ $attrs['number'] }}
<br>
{{ number }}
</div>
</section>
</template>
<script>
export default {
props: {
number: {
type: number,
default: 0
}
},
mounted() {
console.log(this.$attrs);
console.log(this.$listeners);
this.$emit('isOpen');
this.$emit('setData');
//等同于下面两个
//this.$listeners.isOpen();
//this.$listeners.setData();
}
};
</script>
使用v-bind="$attrs"时 inheritAttrs属性的用法
export default {
name: 'Son',
inheritAttrs: false, //可选值 true/false
props: {
age: {
type: Number,
default: 0,
}
}
}
-
下图是设置inheritAttrs: false时候dom树上的展示
-
下图是设置inheritAttrs: true时候dom树上的展示
关键
- v-on="将父组件标签上的自定义事件向下传递其子组件可以直接通过emit(eventName)的方式调用。 vm.listeners: 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。
- 是vm.$attrs :包含了父作用域中props对象为接收的属性(class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),
- vm.$attrs的用法中,假若三层结构中,2级和3级用props对象去接收同一个值,那么第三级将访问不到这个属性,除非在2级中单独对这个属性传递到3级
- v-bind="$attrs": 将调用组件时的组件标签上绑定的非props的特性(class和style除外)向下传递。在子组件中应当添加inheritAttrs: false(可避免避免绑定属性出现在在子组件的根元素上)。
- this.listeners 获取到的值都是json的形式,