1、全局事件总线(推荐)
总线:bus(暂时用x替代)
可以实现任意组件间的通信(父、子间仍然是props最方便),下面是原理图
仍然是下面的例子
1、首先是写让所有组件(vc)都可见的X,所有的vc都是VueComponent所new出来的,复习之前的(单文件组件)知道每个组件都是新的VueComponent,所以说不可以,记住之前的原型图,应该直接写在Vue原型对象上,他是唯一的,且vc和vm都能够访问它
下图中vc组件通过黄色的线访问vue原型对象的X
因为是在main.js引入的Vue,所以说在main.js里面操作Vue,给他加上X
然后就可以正常在其他组件访问X
mounted是页面挂载完成自动运行
然后是考虑调用$on,$off,$emit的问题,X就是普通Object类型的对象,身上是没有$.....的方法的,然后直接x.$on因为x没有,就找到x的Object原型,仍然没有,所以说不能直接将X定义为对象
$on、$off、$emit都在Vue的原型对象上,所以说组件实例对象(this)能够直接调用$on,$off,$emit。为了X能够找到这三个方法,所以说x也应该定义为vc或者vm,这样就可以找到Vue的原型对象,然后找到Vue原型对象上的这三个方法
//回看之前57集,Demo是Vuecomponent,d就是组件实例对象即vc
const Demo = Vue.extend({})
const d = new Demo()
Vue.prototype.x = d
但是仍然可以改进,下面是标准写法(上面是vc写法,下面是vm写法):
//beforeCreate是生命周期钩子,此时的this是当前new出来的vm
//此时模板还没有解析,数据监测和代理都没有完成,所以说这时先把原型上面需要放的放好即x
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.x= this //安装全局事件总线,this就是当前未完全体的vm
},
})
实际上x需要写成$bus更常见,$是Api自带的无实际含义
所以说为了实现Student向School数据学生名
## 全局事件总线(GlobalEventBus)
1. 一种组件间通信的方式,适用于<span style="color:red">任意组件间通信</span>。
2. 安装全局事件总线:
```js
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
},
......
})
```
3. 使用事件总线:
1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的<span style="color:red">回调留在A组件自身。</span>
```js
methods(){
demo(data){......}
}
......
mounted() {
this.$bus.$on('xxxx',this.demo)
}
```
2. 提供数据:```this.$bus.$emit('xxxx',数据)```
4. 最好在beforeDestroy钩子中,用$off去解绑<span style="color:red">当前组件所用到的</span>事件。
2、消息订阅与发布
同样可以在组件间传输数据
1、订阅消息:消息名(我的手机号)
2、发布消息:消息内容(他需要发给我的内容)
A组件内定阅一个消息demo,随后指定其回调为test
C组件发布消息名demo,携带数据666,因为A定阅了demo,所以说test会触发,666以参数的形式被传到test中,有许多消息订阅相关js库,常用为pubsub-js
和上面全局事件总线一样,把学生名从Student传到School当中
安装完js库后,再引入。记住School和Student当中都要引入。
上面的全局总线是在school组件挂载完毕就给$bus绑定hello事件;现在是挂载完毕了立刻去定阅一个消息。
下面是School’组件的js代码,被注释掉的是全局事件总线,注意区别
subscribe:订阅 unsubscribe:取消订阅 publish:发布
//hello是定阅消息名,msgName消息名(也是hello),data是接收返回数据的参数
pubsub.subscribe(‘hello’,function(msgName,data){
函数体
})
//在组件销毁后同样需要取消定阅,beforeDestroy之前有讲解
//pubsub.unsubscribe(id)的参数是每次定阅的消息的ID(自动生成,代码中使用pubId接收此ID,取消定阅也是通过此ID)
pubsub.unsubscribe(this.pubId)总结:接收方subscribe订阅消息,发送方publish消息。订阅和发布的消息名保持一致。订阅方需要设置回调函数,发布方需要写数据
//School当中订阅消息
mounted() {
// console.log('School',this)
/* this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
}) */
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
})
},
beforeDestroy() {
// this.$bus.$off('hello')
pubsub.unsubscribe(this.pubId)
}
//Student当中发布消息
methods: {
sendStudentName(){
// this.$bus.$emit('hello',this.name)
pubsub.publish('hello',666)
}
}
补充:
消息订阅如果不用箭头函数写输出的this为undefine,因为需要向vm的data传数据,所以说写成箭头函数形式,下面的不推荐
this.pubId = pubsub.subscribe('hello',function(msgName,data){
console.log(this)//undefine
console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
})