思路:各种组件间想要通信,可以利用一个第三方。比如说,A组件想给B组件传值,B组件先通过这个第三方利用$on绑定自定义事件,然会B组件会有一个回调函数,A组件再通过$emit触发这个自定义事件,用参数的形式把值带过去,B组件将会在回调函数中接收到它。
1.那么问题来了:这个第三方($EventBus)应该满足什么条件呢?
1.要保证所有的组件都能看见它($EventBus)
2.要保证它身上有$on,$emit,$off
2.继续探索。。。
怎样才能保证所有的组件能看到它呢?
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
怎样才能保证它能调用$on,$off,$emit呢?
必须是那个创建组件,组件自动给你生成的VueComponent,也就是通过Vue.extend()生成的,但是每个组件生成的VC都不唯一,所以后面就利用vm,也就是new Vue中的this指向vm,且唯一
综上所述,这个$EventBus因该设计为:
new Vue({
render: h => h(App),
beforeCreate() {
Vue.prototype.$EventBus = this //安装全局事件总线
},
}).$mount('#app')
3.组件传值步骤
1. 安装全局事件总线
new Vue({
render: h => h(App),
beforeCreate() {
Vue.prototype.$EventBus = this //安装全局事件总线
},
}).$mount('#app')
2.在接收值的那个组件身上用$on绑定自定义事件
<template>
<div class="student">
<h3>我是Student组件</h3>
<ul v-for="(p,index) in person" :key="index">
<li>{{p.name}}</li>
<li>{{p.id}}</li>
<li>{{p.age}}</li>
</ul>
</div>
</template>
<script>
export default {
name:'Student',
data() {
return {
person:''
}
},
mounted() {
this.$EventBus.$on('sendPMessage',(data)=>{
console.log('我收到了School传来的数据',data);
this.person = data;
})
},
beforeDestroy() {
this.$bus.$off('hello')
},
}
</script>
3.在发送值的那个组件身上用$emit去触发自定义事件,并携带需要传的参数
<button @click="sendPersonMessage">把perdon信息给student组件</button>
<script>
export default {
name:'School',
data() {
return {
person:[
{id:'001',name:'小明',age:11},
{id:'002',name:'小红',age:11},
{id:'003',name:'小黄',age:11},
]
}
},
methods:{
sendPersonMessage(){
this.$EventBus.$emit('sendPMessage',this.person)
}
}
}
</script>
补充
-
使用事件总线:
-
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){ demo(data){......} } ...... mounted() { this.$bus.$on('xxxx',this.demo) } -
提供数据:
this.$bus.$emit('xxxx',数据)
-
-
最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。