前段时间,同事发现一个弹窗组件被多个页面复用,而后点击按钮出现了屡次响应。明明页面都会被销毁掉的呀,为啥还会出现重复调用呢。html
其实之前我也碰到过一两次,不知道啥状况后来没有再复现,再加上工期紧,当时就没有引发重视。此次同事碰到了,屡次试验复现了。才深知当时挖的大坑啊没有填。vue
因此此次就单独弄了个demo专门复现并解决这个问题。也但愿吸收教训,之后碰到问题都要记录下来,尽早早早早早解决啊,否则都是坑。git
另外,文章里的关于父子组件的全局事件监听是错误的选择,请你们不要使用这种。(可是兄弟组件能够用文中这种全局监听的方式)
请用官方例子(遇到问题,请多用官方,否则直接参考其余同窗的思路极可能挖坑。这里是之前直接搜索到eventbus的实现方式,请引觉得戒,哈哈,我就作个反面教材吧
传送门在此github
首先我写了一个dialogx的小组件,里面只有一个点击按钮。当点击的时候,会触发一个btnClick
的事件。数组
而后我又写了两个页面用来测试重复响应。下面是 test1.vue
,至于test2
也同样,就不从新放图了。ide
而后,我们来点点点点点点!就能发现,在test2
页面发起的事件,而test1
也响应了,这属于重复响应是不符合咱们的项目须要的。测试
这...是咋回事~~??ui
通过查询相关资料,肯定了问题在于没有过去的销毁事件响应。this
好,咱们出发去加上销毁逻辑。spa
因而我在dialogx.vue
中加入如下代码,在路由切换组件被销毁的时候,对btnClick
事件进行销毁。顺便打印一下 this.$root
看看里面是个啥结构。
而后就有了如下的操做,竟然...竟然 test2.vue 无法响应了。WTF,这又是啥状况。
冷静下来,好好分析。首先这种状况是由于咱们加了销毁操做致使的,因此确定是销毁的问题。
那么咱们继续追踪。发现路由切换的各类操做的顺序是这样的。
这说明 什么问题?
新页面的
created
先执行,而后开始逐渐销毁老页面。仔细看看,咱们能发现问题,test2.vue
在建立监听事件的时候,是在dialogx.vue
销毁以前的。人家刚建立好监听事件,因为执行顺序问题,被子组件给清除了,因此test2.vue
在点击发射时,是拦截不到的。
好,既然由于执行顺序的问题,那咱们把监听事件注册放在 mounted
里。
果真,成功了。
对于事件的触发和监听,由于咱们这是用 eventbus
实现的。为了看看里面具体是为何,因而我打印了 this.$root
看看更细节的是为何。
首先,每一次监听 this.$root.$on('btnClick')
都是一次事件注册,而后我在打印的结果里,找到了如下内容。
btnClick
是一个数组,这就意味着每一次btnClick
事件注册,都是往里存一个处理方法。
而后为了验证个人想法,我把 test2.vue
中的监听事件去了,直接看咱们的 $off
效果。
是 null
,这就解释了为何,刚才监听事件写在 created
里,为何不生效了,由于整个事件都被设置为 null
了。
为了达到组件复用不产生重复响应的问题。咱们能够以下作。
1.在子组件里的
destroyed
方法里,对事件进行销毁操做($off)
2.在页面中mounted
方法中进行事件监听。
GitHub代码地址:https://github.com/XuXiaoGH/v...
此次是一次异常排查过程的记录,若是对你有些许帮助,不妨收藏点个赞,这将是我继续的很大动力。
ps: GIF截图软件是 LICEcap ,很是好用,推荐一下。