一、全局事件总线
全局事件总线,是组件间的一种通信方式,适用于任何组件间通信。
首先我们在 main.js 中,安装全局事件总线
import Vue from 'vue';
import App from './App.vue';
Vue.config.productionTip = false;
new Vue({
el:"#app",
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus = this;
}
})
$bus
定义在Vue.prototype,因此$bus
对所有组件可见,即所有组件可通过this.$bus
访问。
$bus
被赋值为this,即vm实例,因此$bus
拥有vm实例上的所有属性和方法,如$emit、$on、$off
,所有组件实例对象的原型对象的原型对象就是 Vue 的原型对象。
使用事件总线
$bus.$on
,监听事件。Employee 组件中定义了监听事件,监听 demo 事件;
$bus.$emit
,触发事件。Company 组件中定义了触发事件,点击按钮执行 sendMessage 回调,该回调将触发 demo 事件。
$off(eventName)
,解绑自定义事件监听,最好在 beforeDestory 钩子函数中解绑
$once(eventName, listener)
,绑定事件监听, 但只能处理一次。
接收数据:
methods(){
demo(data){......} //提前配置好 demo 函数
}
mounted(){
this.$bus.$on('xxx',this.demo) //绑定自定事件时,回调要么配置在 methods中,要么用箭头函数,否则 this 指向会出问题
}
提供数据:this.$bus.$emit('xxx',数据)
指定事件总线对象
new Vue({
beforeCreate () { // 尽量早的执行挂载全局事件总线对象的操作
Vue.prototype.$globalEventBus = this
},}).$mount('#root')
绑定事件
this.$globalEventBus.$on('deleteTodo', this.deleteTodo)
分发事件
this.$globalEventBus.$emit('deleteTodo', this.index)
解绑事件
this.$globalEventBus.$off('deleteTodo')
二、消息订阅与发布
一种组件间通信的方式,适用于任意组件间通信。其思想类似于全局事件总线,事件总线只适用于平级组件间通信。
它包含以下操作:
(1) 订阅消息 --对应绑定事件监听
(2) 发布消息 --分发事件
(3) 取消消息订阅 --解绑事件监听
使用消息我们需要引入一个消息订阅与发布的第三方实现库: PubSubJS
使用 PubSubJS
在线文档: https://github.com/mroderick/PubSubJS
使用步骤:
- 下载
npm install -S pubsub-js
- 引入
import PubSub from 'pubsub-js'
- 订阅消息
PubSub.subscribe(‘msgName’, functon(msgName, data){ })
- 发布消息, 触发订阅的回调函数调用
PubSub.publish(‘msgName’, data)
- 取消消息的订阅
PubSub.unsubscribe(token)
举例:
Student.vue
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">把学生名给School组件</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:'Student',
data() {
return {
name:'张三',
sex:'男',
}
},
mounted() {
// console.log('Student',this.x)
},
methods: {
sendStudentName(){
// this.$bus.$emit('hello',this.name)
pubsub.publish('hello',666)
}
},
}
</script>
<style lang="less" scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
School.vue
<template>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:'School',
data() {
return {
name:'qdu',
address:'青岛',
}
},
mounted() {
// console.log('School',this)
/* this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
}) */
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
console.log(this)
// console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
})
},
beforeDestroy() {
// this.$bus.$off('hello')
pubsub.unsubscribe(this.pubId)
},
}
</script>
<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
</style>