如果存在组件之间层级大于2层,中间需要一个过渡层的时候,属性和事件的上传下达越简洁越好,重点就是采用vue里的$atts 和事件 $listeners,先打印看看这两者是什么玩意,

1
2
$attrs: object,
$listeners: object

两者都是绑定在组件里的,且是对象类型,所以在组件阔以之间用this.$attrs.info去获取祖父组件传来的info信息。

以下有三个组件,三者之间都是相关有联系的,阔以称之为 祖父组件、父组件以及子组件。
伪代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// grandParent.vue
<template>
<div class="home">
<Parent
:childMsg='childMsg'
@triggerClickChild='triggerClickChild'
info='父组件'
/>
</div>

</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Parent from '../components/parent.vue'; // @ is an alias to /src

@Component({
components: {
Parent,
},
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// parent.vue
<Child
label='子组件信息'
class='child'
v-bind='$attrs'
v-on='$listeners'
@triggerClickChild='parentC'
/>

import Child from './child.vue'
@Component({
components: {
Child
}
})
export default class Parent extends Vue {
@Prop() private childMsg!: any; // 此时childMsg信息已用所以不会传递到子组件
private parentC(key: string) {
console.log(key, '中间层截胡')
}
private mounted() {
console.log(this.childMsg, 'props')
console.log(this, '中间组件')
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// child本身的组件
<div class="hello">
<h1 @click='triggerClickChild'>{{$attrs}}</h1>
</div>

@Component({
inheritAttrs: false
})
export default class HelloWorld extends Vue {
private triggerClickChild() {
this.$emit('triggerClickChild', 'triggerClickChild子孙组件');
}
private mounted() {
console.log(this, 'attrs') // {info: '',label: '', }
console.log(this.$listeners) // fn triggerClickChild
}
}

梳理以上几个组件发现这几点:
1.v-bind=’$atts’ 和 v-on=’$listeners’只能用于中间组件的传递,也就是起到承上启下的作用
2.中间组件接受的props,一旦被采用,也就无法传递到下一层。but事件,中间层阔以截胡,因为事件是由下往上,父组件和祖父组件都能接收到
3.有个弊端,如果中间层需要对数据进行二次加工,$attrs也就无用武之地,所以最好就是在顶层组件进行处理,如果处理不了就只能Props一层层传
4.当然最大的优势还是免除一层层传递,事件和属性这样简写一下高效了许多。