本来单个模块使用的情况下,都没有什么问题,但是如果从边界防控切换到区域防控之后,弹框就出不来了。然后我在那个地图文件中console.log了一下,发现该文件确确实实使用bus发出了一个自定义事件this.bus.$emit(‘olMapClick’, evt) 。然后发现是切换之后,在边界防控和区域防控中,bus都接收不到该事件。所以导致了弹框不会触发。本来想的是是不是因为地图多次初始化的问题导致的,但是排查了很久,感觉没有问题,后面才确定为bus传递事件的问题。
问题解决开始1:
bus的$on接收不到事件,本来觉得这是个简单的小问题,直接百度就行了。然后百度就会给出这样的答案:
问题原因:因为我的代码中on()监听事件执行了,Vue中并没有储存监听事件,所以无法监听到数据。即使用总线方式实现兄弟组件间的传值时,必须保证 $on()监听事件先被创建,否则无法正常监听消息
尝试第一次解决:在地图文件中 e m i t 的 时 候 , 加 了 一 个 emit的时候,加了一个 emit的时候,加了一个nexTick或者setTimeOut都试了一下,保证每个模块的 o n 都 在 on都在 on都在emit之前,发现没有什么用,切换之后还是接收不到该事件。
问题解决开始2:
既然我的 o n 都 在 on都在 on都在emit之前,那么单个文件来看,肯定都没有问题。那么就将两个模块的文件一起看。然后就发现:为了不增加内存,在每个模块的beforeDestroy里面,我都会去释放这个事件 this.bus.$off(‘olMapClick’)。
表面上看确实没有任何问题,因为这是正常操作,bus监听之后,在离开之后再取消监听。
But,当两个模块的文件连起来之后,就出现问题了。
因为我是在created中来 o n 这 个 事 件 的 ( t h i s . b u s . on这个事件的(this.bus. on这个事件的(this.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. on接收不到事件的原因:此时切换模块(A切换到B)的操作就相当于是:B模块created中使用了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取消了监听。切换时,就会出现这种问题。记录一下,下次就不用这样子找到秃头了。