一、全局引入事件总线
//main.js
import vue from 'vue
import App from './App.vue
//全局注册事件总线
vue.prototype.$bus = new vue();
const app = createVue();
app.mount('#app');
二、使用步骤
1.发送事件
代码如下(示例):
//路径:A.vue
<template>
<div @click="sendBus">点击发送bus事件</div>
</template>
<script>
methods:{
data(){
return {
user:{
name:"张三",
age:18
}
}
},
sendBus(){
this.$bus.$emit('busEvent',this.user);
//如果出现上面的方式$on获取不到数据的情况,可以使用下面的方式,这是通过延迟发送的方法来解决,$on没有接收到的问题
/*
setTimeout(()=>{
this.$bus.$emit('busEvent',this.user)
},700);
*/
}
}
</script>
2.接收事件
代码如下(示例):
//路径:B.vue
<template>
<div @click="sendBus">点击发送bus事件</div>
</template>
<script>
methods:{
data(){
return {
userList:{}
}
},
mounted(){
this.$bus.$on('busEvent',val=>{
this.userList = val;
})
},
beforeDestory(){
//销毁事件总线,防止多次触发。
this.$bus.$off('busEvent');
}
</script>
三、实际项目中的问题
当我们在A组件中点击按钮跳转另一个页面B组件,并传递数据给B组件。我发现传送过去的数据是
undefined或者有时候没有打印
,也有的时候出现第一次打印undefined,但是返回上一个页面重新打印就有数据了
。错误我就不展示了,直接分析原因。
1.第一次打印为undefied,然后返回页面打印正常。
要解决这个问题,主要是在于当我们使用
$emit
发送数据的时候,要保证$on
可以监听到这个事件,这个问题的原因就是两个组件的生命周期不同,导致B组件没有监听到A组件发送的事件。
这是两个组件的生命周期
可以看到我们想要在组件B的created中
监听的话,我们可以在beroreDestroy,或者destroyed中
发送事件。
这时候显示打印数据成功,但是我们返回点击会出现多次打印的情况
产生问题的原因:其实就是页面切换的会生成新的 clickHandler,所以当 eventBus.$on(‘click’, clickHandler),的时候eventBus发现 clickHandler 总是新的,所以每次都注册成功。而eventBus是全局的,它不会随着你页面切换而重新执行生命周期,所以click下的clickHandler 会越来越多。
2.解决多次触发的问题
代码如下:
//在B组件的beforeDestory生命周期内销毁事件总线
beforeDestory(){
this.$bus.$off('busEvent',this.userList);
}