VUE 爬坑之旅-- eventBus 事件总线的基本使用和重复触发事件问题的解决
在单页应用中,在 A 页面中触发事件,然后在 B 页面中对这个事件进行响应是一个很常见的需求,那么当有这种需求的时候要怎么实现呢。有两种方案可以实现:1. 使用 vuex 状态管理,当触发事件时,改变 vuex 中的状态,然后在需要响应事件的地方用 watch 监听这个状态,当状态改变时,响应事件。2. 使用 eventBus 事件总线,当触发事件时,发送一个通知出去,在需要响应的地方接收...
在单页应用中,在 A 页面中触发事件,然后在 B 页面中对这个事件进行响应是一个很常见的需求,那么当有这种需求的时候要怎么实现呢。有两种方案可以实现:
1. 使用 vuex 状态管理,当触发事件时,改变 vuex 中的状态,然后在需要响应事件的地方用 watch 监听这个状态,当状态改变时,响应事件。
2. 使用 eventBus 事件总线,当触发事件时,发送一个通知出去,在需要响应的地方接收这个通知,响应事件。
方案一使用起来略复杂,有些东西也不是很好处理,综合考虑下来还是采用方案二,方案二比较符合正常的思维方式,使用也较方便。
基本使用
在官方文档上,对 eventbus 的介绍很简单,基本就是一笔带过,这里就来说下基本的使用方法。
创建 EventBus
//新建一个 js 文件,写下如下代码就创建好了一个 eventbus,没错,就是这么简单
import Vue from 'vue'
export default new Vue;
在 main.js 中导入 eventbus ,然后将它挂载到 vue 的原型上,这样就可以全局调用了
import bus from './utils/eventBus'
Vue.prototype.bus = bus;
发送事件
在触发事件的地方发送事件
this.bus.$emit(this.$route.path);
$emit(),里面需要一个string 类型的事件名,我这里是用的当前路由的 path 作为事件名。
接收事件
事件已经发送,接下来只需要在需要接收事件的地方接收这个事件,然后对事件进行响应就可以了。
this.bus.$on(this.$route.path,()=>{
this.getData();
})
接收事件的时候同样需要一个事件名,然后是一个函数来进行事件响应,我这里是调用了下获取数据的接口。
这样,整个事件从发送到接收并响应就完成,是不是很简单。
事件重复触发的问题
坑一
正当你开心的准备玩耍的时候却发现好像有哪里不对劲,怎么事件会重复触发了,而且每次切换过路由后,事件执行次数就会加一,这怎么行,假如用户非常频繁的切换页面,那事件执行次数不是会越来越多,到最后不是要爆炸。
一番搜索后终于找到了原因,原来这是因为我们的事件是全局的,它并不会随着组件的销毁而自动注销,需要我们手动调用注销方法来注销。知道了问题原因就好办了,我们可以在组件的 beforeDestroy ,或 destroy 生命周期中执行注销方法,手动注销事件。
beforeDestroy() {
//组件销毁前需要解绑事件。否则会出现重复触发事件的问题
this.bus.$off(this.$route.path);
},
这样就完成了事件的注销操作,可以注销掉当前事件。
坑二
你以为这样就可以好好玩耍了吗,NO,NO,NO。
虽然我们在生命周期中注销了事件,然而还是发现事件会多次执行,问题依旧在,那是什么原因呢?
经过打印日志后发现,问题出在事件名上面,由于我是用的 this.
route.path作为事件名,在注销的时候也是想当然的用this.
r
o
u
t
e
.
p
a
t
h
作
为
事
件
名
,
在
注
销
的
时
候
也
是
想
当
然
的
用
t
h
i
s
.
toure.path 作为注销事件名。观察日志后发现,在 beforeDestroy 中, this.$route.path 根本就不是我们发送和响应事件时候的路由了,而是将要跳转页面的路由。
这其实就是生命周期的问题了,在 beforeDestroy 和 destroy 生命周期中,用 this.$route.path 获取到的其实是下一个页面的 path ,注意这一点,问题即可解决。解决方案也很简单,就是在当前页面用一个变量将当前路由存下来,用这个变量作为事件名注销事件即可。
更多推荐
所有评论(0)