非父子组件传值通信
方式一:
1.新建一个js文件,例如assects/VueEvent.js
然后引入vue: import Vue from 'vue';
实例化vue: var VueEvent=new Vue(); //创建一个空的实例
最后暴露这个实例: export default VueEvent;
2.在要广播的地方引入上面定义的实例
// 根据自己定义的路径引入实例
import VueEvent from '../assects/VueEvent.js';
3.通过VueEvent.$emit('自定义事件名称','需要传输的数据'); 进行广播
emitNews(){
// 广播事件
VueEvent.$emit('myEvent', 'hello world!');
}
4.在接收数据的地方通过$on接收广播的数据 VueEvent.$on('事件名称',function(){ }),或者VueEvent.$on('事件名称',() => { })
mounted(){
// 监听广播,接收数据
VueEvent.$on('myEvent',function(data){
console.log(data); // 输出 hello world!
});
}
方拾二
1.先在main.js里生成一个自定义事件,此事件为全局事件
new Vue({
router,
store,
render: h => h(App),
data() {
return {
// 自定义事件
myEvent: new Vue()
}
}
}).$mount('#app')
2.用法
在需要的页面进行事件绑定 :
// myEvent是main.js里设置的空的vue实例名,trans是自定义事件名,value是自定义要传输的值
this.$root.myEvent.$emit("trans", value);
在需要的页面监听事件:
this.$root.myEvent.$on("trans", msg => { // 监听trans事件,从回调函数中拿出值
console.log("trans事件传过来的值: " + msg);
});
问题:
有时候会发生事件只被emit触发了一次,但是回调函数却被执行了多次的现象。这种现象往往发生在页面跳转退出后重新进入的时候。
产生原因:
this.$root.myEvent.$on实际是向myEvent容器中添加一个事件监听器,当页面跳转时,原来的vue组件被注销,
但是原来vue组件向myEvent容器中添加的事件监听器并不会被移除。因此,当下次进入这个vue组件对应的页
面时,执行到this.$root.myEvent.$on时,又会向myEvent容器中添加一个重复的事件监听器,以此类推,导
致myEvent容器中有很多个一模一样的事件监听器,从而导致事件只被触发一次,但是回调函数被执行多次的现象。
解决方案:
在vue实例销毁之前,即在vue组件的beforeDetory钩子函数中将本vue组件往myEvent容器中添加
的时间监听器全部手动移除。this.$root.myEvent.$off("事件名");
beforeDestroy() {
this.$root.myEvent.$off("trans");
}
方式一中也会有这个问题,解决方法同方式二