【vue-router + eventbus】在页面跳转时使用eventbus传递数据

遇到的问题

基本思路:A页面使用eventbus触发B页面的方法并跳转到B页面,B页面监听
问题如下:

  1. B页面bus.$on("method")无效,没有监听到任何触发
  2. 第一次触发监听不到,之后的可以监听到
  3. 方法执行次数随着后续触发逐渐增多,例如第一次点击执行了一次,第二次点击执行了两次,以此类推
    代码如下:
//bus.js
import Vue from 'vue'
export default new Vue();
//A.vue
import bus from "bus.js"
search(val) {
	bus.$emit("fuzzySearch", val);
	this.$router.push("result");
}
//B.vue
import bus from "bus.js"
mounted() {
	bus.$on("fuzzySearch", data => {
		console.log(data);
	});
}

问题解决

第三个问题之前就遇到过,原因在于bus.$on不会自动销毁,可以想象成每有一个bus.$on,就会在eventbus中注册一次,并且一直存在(不手动关闭的话),所以下一次点击触发on事件,B页面相当于可以监听到上一次点击注册的那个事件,因此就会执行两次,往后递增。
解决方法就是在B页面销毁前手动关闭。可以认为,on和off必须成对出现。

//B.vue
beforeDestroy() {
	bus.$off("fuzzySearch");
}

至于第一和第二个问题,都是涉及到Vue实例的生命周期。大致可以认为是这样一个流程:
beforeCreate() ===> created() ===> beforeMount() ===> mounted() ===> beforeDestroy() ===> destroyed()
最开始的时候,我把bus.$on写在了B的mounted()函数中,但由于涉及到路由跳转问题,就得看两个页面的生命周期有一个怎样的交替执行,可以参考这篇文章中的测试结果。
这里有两个地方需要注意:

  1. 在A页面的普通方法中emit是无法被B页面监听到的,因为此时我们还在A页面,B页面还没有create,自然无法注册on事件,因此我们需要在B页面已经创建出来之后(并且on事件已经注册)才去emit,最好就是把emit写在A的beforeDestroy()中,保证emit触发时,B页面已创建
  2. B页面mount时,A页面已经销毁,而我们需要在A页面销毁前注册on事件,否则也是监听不到的,因此,B页面的on事件应该在created()中注册

总结即是:on事件一定要在emit之前注册

最后代码

//A.vue
import bus from "bus.js"
  beforeDestroy() {
    var val = this.search_val;
    bus.$emit("fuzzySearch", val);
  },

methods: {
	search(value) {
     	this.search_val = value;
		router.push("result");
    }
}
//B.vue
import bus from "bus.js"
created() {
	bus.$on("fuzzySearch", data => {
		console.log(data);
	});
},

beforeDestroy() {
	bus.$off("fuzzySearch");
}

你可能感兴趣的:(前端)