阅读 2208

Vue eventbus 使用中的重复触发解决方案及存在的Bug

前言

        大家还在吗有一周时间不见了吧,那么这周讲一些什么呢,不知道你们是否还记得我上周说过的这周要讲eventbus,其实eventbus还是有bug的,那么废话不多说直接开始正题

eventbus重复触发的bug

        记得上周我讲过的demo吗,现在整理一下

//main.js
window.Bus =new Vue();
//a.vue
...
 beforeCreate(){
    Bus.$on("this_change",[1,2])
 }
....
//b.vue
...
created(){
    Bus.$on("this_change",(em) => {
        //这样就可以打印出来刚刚传过来的1和2了
        console.log(em[1],em[2]); 
    });
},
beforeDestroy(){
    //最后不要忘了删除传输事件
    Bus.$off("this_change")
}
复制代码

        很简单对吧,那么你就大错特错了因为我们的理想状态是使用完一次组件之后就立即删除该组件以保证传输事件的删除,但是实际情况呢,有很大不同这点大家应该都想到了对吧,所以我们接下来要讲的是实际场景中的应用。

        顺便说一嘴上面代码块的代码有很多都是省略的,这个大家要拿去做demo的时候要注意,代码补全。

        那么我们下面要讲的场景是我这边真实发生的一个场景,因为我做的是关于区块链金融部分的内容所以在实际需求中我做的页面并不需要刷新和缓存数据但是有一点就是,在不刷新页面或组件的情况下要通过子组件之间互相传递数据,这点大家应该能瞬间想到很多吧,比如两个子组件不公用ajax数据,每个组件单独请求,又或者是吧数据存在本地然后调用,又或者是把数据传入最上层父组件之后再通过父组件分发的形式传入对应的子组件完成交互。但是大家不知道有没想过这样几个方法不仅费力不讨好而且子组件之间传值一旦多了demo还好但是到项目这块是不是就不好控制了,相对于比较小的项目来说eventbus的使用还是比较省事省力的,用较少的代码完成交互。

        说了这么多解决方案是什么,那当然就是eventbus来解决喽,但是大家注意刚才我说的在组件和页面不刷新的前提下了吗,这个时候我们就应该能想到,beforeDestroy()的Bus.$off是不是就不会销毁一直存在呢,答案是肯定的,但是更绝望的是你如果在这个组件上多注册几个传输事件和接收事件的话那么这些传输事件和接收事件来回切换的话那么你试着打印就会发现这些事件在点击多了以后会以递增的方式进行触发,这就是eventbus在实际使用和做demo的区别。

        回归正题这种bug怎么解决呢

        第一种是在使用过Bus.$on之后立即使用Bus.$off方法,但是做过之后发现了一个说不大也不大说不小也的bug就是在Bus.$0ff之后这个触发事件只会触发一次,那么上网上查了一下一篇尤大神的回答,很是不错,就贴在下面了网址

github.com/vuejs/vue/i…

        这个回答里面有说mixin这个方法是可以解决的至于怎么去解决这个问题我会在下周的文章里讲到也是下周文章的一个主题吧,至于这里的解决方案有一种比较快速的解决方案介绍给大家vue-happy-bus这个插件专门是为Busevent而生的,这个之后再讲,先讲一下Bus.$off要放在那里

//b.vue
//我把上面的东西拿过来是为了大家能看得清楚
created(){
    Bus.$on("this_change",(em) => {
        //这样就可以打印出来刚刚传过来的1和2了
        console.log(em[1],em[2]); 
        //这里就是我说的在使用之后立即删除这个事件以防多次触发
        Bus.$off("this_change",em);
    });
}
复制代码

        但是上面的这个方法还是有一些小问题,比如有事触发不了,或者有时会报错,这几个都不是最佳解决方案,但是上面说的vue-happy-bus这个插件就完美解决了此问题,这个我们留在下下周的文章中我会花一篇文章的时间讲解这个组件的实现思想。

vue-happy-bus

        大家也看到了上面我这么推崇vue-happy-bus这个组件你们是不是在想有何不同,这个组件,他究竟解决了我们的问题没,这个我可以很负责任的告诉大家这个确实解决了我们现在的所需,废话不多说先看代码

//npm或cnpm下载
npm install vue-happy-bus --save
cnpm install vue-happy-bus --save
//main.js中引用
//bus状态管理
import BusFactory from 'vue-happy-bus'
//使用全局变量引用
Vue.prototype.$BusFactory=BusFactory;
//a.vue中引用这里注意一点每个使用Bus的组件中都要在data中注册这个事件Bus:this.$BusFactory(this)这样才能调用其中这个this指向vue原型
....
data:function(){
    Bus:this.$BusFactory(this)
},
methods:{
    //在点击事件上执行这个方法就能传递参数
    click_me:function(){
        this.Bus.$emit("clear_me","clear_me")
    }
}
....
//b.vue
....
created(){
     this.Bus.$on("clear_me",(em) => {
        console.log(em)
     }
}
....
复制代码

        是不不是在奇怪为什么我没用Bus.$off方法因为在我们调用Bus.$on的时候vue-happy-bus就已经帮我们创建过off事件并自动挂载在事件结束的时候调用,这样我们使用一次那么它就会直接把Bus.$off自动调用一次,就相当于是删除了整个事件,就是这样,具体的还要看我下下周的文章。

        好了这次把上次的坑给埋了又留下两个坑等着我去踩,那么大家这次的分享就到这,谢谢观看,想要提问的可以在下面评论区讨论。