在vue中使用父子组件通信的的时候,人们肯定会想到props,$emit
假如有A组件B组件和C组件
关系为:A组件是B组件的父组件,B组件是C组件的父组件,
如果A组件要跟C组件通信,可能的操作是,A往B传值,B再往A传值;C往B传值,B再往A传值
都得通过B这一程,这样子做也不是不行,但是耦合度太高了,不便于维护,代码可读性也不好。
我们可以$attrs
与$listeners
来解决这个问题
A组件
<template>
<div class="hello">
A组件:{{ formData }}
<Son :message="messageB" :messagec="messagec" @getBData="getBData" @getCData="getCData"></Son>
</div>
</template>
<script>
export default {
components: {
Son: resolve => { require(['@/components/Son.vue'], resolve) }
},
data () {
return {
messageB: '传给B的数据',
messagec: '传给C的数据',
formData: ''
}
},
methods: {
getBData (val) {
this.formData = val
},
getCData (val) {
this.formData = val
}
}
}
</script>
<style scoped>
</style>
B组件
<template>
<div class="son">
B组件
<input v-model="myMessage" @input="getBData" />
<gradson v-bind="$attrs" v-on="$listeners"></gradson>
</div>
</template>
<script>
export default {
data () {
return {
myMessage: ''
}
},
created () {
this.myMessage = this.message
},
props: {
message: {
type: String,
default: ''
}
},
components: {
Gradson: resolve => { require(['./Gradson.vue'], resolve) }
},
computed: {},
mounted () {},
methods: {
getBData () {
this.$emit('getBData', this.myMessage)
}
}
}
</script>
<style scoped>
</style>
C组件
<template>
<div class="gradson">
C组件
<input v-model="myMessage" @input="getCData"/>
</div>
</template>
<script>
export default {
data () {
return {
myMessage: ''
}
},
created () {
this.myMessage = this.$attrs.messagec
},
props: {},
components: {},
computed: {},
mounted () {
},
methods: {
getCData () {
this.$emit('getCData', this.myMessage)
}
}
}
</script>
<style scoped>
</style>
在B组件里使用C组件的时候,v-bind="$attrs
",$attrs
里面存放的是B组件porps里意外的的属性
所以在C组件的时候通过$attrs
只能拿到messagec而拿不到messageB的
v-on="$listeners
"使得C组件定义的方法可以传到A组件而不用经过B组件的中转站了
这样就可以使得A与C的数据交互不需要通过B啦