1. 定义
全局事件总线是一种组件间的通信方式,适用于任意组件之间的通信。
事件总线是程序员在工作中的总结,不是新的 api。
思考:全局事件总线思路是这样的:能不能在找一个地方能够让所有的组件看到,第二个有用 $on, $emit $off
等方法。基于此思路,window 对象是 js 内置的全局对象,如果在 window 上面绑定方法或者属性其他地方都可以调用,也就是满足了被任何组件看到的要求,但是 window 没有$on, $emit $off
方法,并且在 window 上面绑定这么多东西也不太好。所以另外一个思路是 vm 是 vue 的实例对象,可以被任意组件发现,vm 也拥有这些方法,所以就在 main.js
入口文件去绑定 vm。这就是事件总线。
2. 安装全局事件总线
new Vue({
....
beforeCreated(){
Vue.property.$bus = this // 安装全局事件总线,$bus 就是当前事件总线的 vm
}
})
3. 使用全局事件总线
- 接收数据:A组件想接收数据,则在 A 组件中给 $bus绑定自定义事件,事件的回调留在 A 组件自身中。
methods(){
demo(data){...}
}
....
mounted(){
this.$bus.$on("xxxx", this.demo)
}
- 提供数据:
this.$bus.$emit('xxxx', 数据)
4. 解绑事件
最好在 beforeDestroy()
钩子中,用 $off()去解绑当前组件中所用到的事件。
5. 代码和案例
现在有 App 父级组件,已经两个兄弟组件 Student 和 School。我们需要把 Student 组件里的 name 值传给 App 和 School。写法,在接收的组件 App 和 School 组件里先定义函数
发送端写法 Student组件写法
<template>
<div id="student">
<h2>学生名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
<button @click="sendStudentName">点击把student名字传给school</button>
<button @click="sendNameToApp">把名字传给app组件</button>
</div>
</template>
....
methods: {
//把数据给Student组件
sendStudentName(){
this.$bus.$emit("getStudnetName2",this.name)
},
//把数据给App组件
sendNameToApp(){
this.$bus.$emit('getStudentName',this.name)
}
}
接收端 App组件写法
mounted(){
this.$bus.$on('getStudentName',(data)=>{
console.log("我是app组件,我收到了数据", data)
this.msg = this.msg + data
})
},
beforeDestroy(){
this.$bus.$off("getStudentName")
}
接收端School组件写法
mounted(){
//this.x即是组件实例对象vc上绑定了一个$on的事件,这个事件名为 hello,后面是回调函数
this.$bus.$on('getStudnetName2',(data)=>{
console.log('我是school组件,我收到了数据', data)
})
},
beforeDestroy(){
this.$bus.$off("getStudnetName2") //在组件销毁时候解绑 hello事件
}
main.js 里安装数据总线写法
// 该文件是整个项目的入口文件
// 引入vue
import Vue from 'vue'
// 引入APP组件,APP组件是整个项目的父组件
import App from './App.vue'
//关闭vue生产提示
Vue.config.productionTip = false
// const Demo = Vue.extend() // Vue.extend() 创建一个 VueComponent
// const d = new Demo() // VueComponent 的实例对象,d是VueComponent的实例对象 vc。vc上面可以访问到 $on, $off
// Vue.prototype.x = d // 这个是用 vc去绑定事件总线
// 创建vue实例对象 -- vm
new Vue({
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus = this //安装事件总线,this 值得是 vm
}
}).$mount('#app')
网友评论