Vue中使用bus.$emit触发自定义事件bus.$on却监听不到任何消息

Vue中使用bus. e m i t 触 发 自 定 义 事 件 b u s . emit触发自定义事件bus. emitbus.on却监听不到任何消息

Bug情况,我这边有两个模块(区域防控和边界防控),分别使用了同一个地图文件,在地图文件中,只要点击了地图,就会使用bus. e m i t 来 发 出 一 个 事 件 , 然 后 每 个 模 块 分 别 使 用 b u s . emit来发出一个事件,然后每个模块分别使用bus. emit使bus.on接收到该事件,就可以对地图的点击做出反应(也就是弹窗)。

如图:

Vue中使用bus.$emit触发自定义事件bus.$on却监听不到任何消息_第1张图片

点击后:
Vue中使用bus.$emit触发自定义事件bus.$on却监听不到任何消息_第2张图片

本来单个模块使用的情况下,都没有什么问题,但是如果从边界防控切换到区域防控之后,弹框就出不来了。然后我在那个地图文件中console.log了一下,发现该文件确确实实使用bus发出了一个自定义事件this.bus.$emit(‘olMapClick’, evt) 。然后发现是切换之后,在边界防控和区域防控中,bus都接收不到该事件。所以导致了弹框不会触发。本来想的是是不是因为地图多次初始化的问题导致的,但是排查了很久,感觉没有问题,后面才确定为bus传递事件的问题。

问题解决开始1:

bus的$on接收不到事件,本来觉得这是个简单的小问题,直接百度就行了。然后百度就会给出这样的答案:

问题原因:因为我的代码中$emit()事件先于 $on()监听事件执行了,Vue中并没有储存监听事件,所以无法监听到数据。即使用总线方式实现兄弟组件间的传值时,必须保证 $on()监听事件先被创建,否则无法正常监听消息

尝试第一次解决:在地图文件中 e m i t 的 时 候 , 加 了 一 个 emit的时候,加了一个 emitnexTick或者setTimeOut都试了一下,保证每个模块的 o n 都 在 on都在 onemit之前,发现没有什么用,切换之后还是接收不到该事件。

问题解决开始2:

既然我的 o n 都 在 on都在 onemit之前,那么单个文件来看,肯定都没有问题。那么就将两个模块的文件一起看。然后就发现:为了不增加内存,在每个模块的beforeDestroy里面,我都会去释放这个事件 this.bus.$off(‘olMapClick’)。

表面上看确实没有任何问题,因为这是正常操作,bus监听之后,在离开之后再取消监听。

But,当两个模块的文件连起来之后,就出现问题了。

因为我是在created中来 o n 这 个 事 件 的 ( t h i s . b u s . on这个事件的(this.bus. onthis.bus.on(‘olMapClick’, this.MapClick))。

解释一下bus o n 接 收 不 到 事 件 的 原 因 : 此 时 切 换 模 块 ( A 切 换 到 B ) 的 操 作 就 相 当 于 是 : B 模 块 c r e a t e d 中 使 用 了 b u s . on接收不到事件的原因:此时切换模块(A切换到B)的操作就相当于是:B模块created中使用了 bus. onABBcreated使bus.on监听了olMapClick的事件,A模块最后的beforeDestroy取消了对olMapClick事件的监听,导致了切换到了B模块之后,就根本没有使用bus.$on来监听olMapClick事件。

这里涉及的知识点为:[vue 旧页面beforeDestory和新页面的生命周期顺序问题]

旧页面beforeDestory执行顺序是在 新页面mounted之前,created之后执行的

所有在beforeDestory执行的某些数据操作如果想在新页面created中生效,则需要改为beforeRouteLeave方法,在数据处理完后调用next()跳转到新页面

最终解决3:

我把每个模块bus取消(bus.$off)监听olMapClick事件的操作放在了 beforeRouteLeave的生命周期钩子函数中了,这样子在模块切换的过程中,就不会对后面这个模块的bus监听产生影响了。

这个bug还是比较隐秘的,涉及的知识点也比较多。主要用于 两个文件都同时在created使用了bus.$on同一个事件时,然后又在beforeDestory取消了监听。切换时,就会出现这种问题。记录一下,下次就不用这样子找到秃头了。

你可能感兴趣的:(vue.js,javascript,前端)