在Vue开发中会遇到大量的组件之间共享数据的情形,针对不同的情形,Vue有相对应的解决方案。比如,父组件向子组件传值可以使用props,复杂项目中不同模块之间传值可以使用Vuex。但是,对于一些简单的项目里的非父子组件来说,它们一方面不适用props,另一方面又没有必要使用Vuex,针对这种情形可以使用中央事件总线(Event Bus)来解决问题。
主要用到vue的$on和$emit事件,但是这两个事件必须在同一个vue实例中:
http://jsrun.pro/yfWKp/edit
同一个实例中的$emit事件会被$on监听捕捉到。使用webpack创建的工程如何共享一个实例呢?我们可以创建一个公共实例,将其作为一个组件引入。
1、创建中央事件总线
可以采用多种方式创建事件总线
(1)
// main.js
import Vue from 'vue';
window.eventBus = new Vue(); // 注册全局事件对象
// 也可以修改Vue的原型链
Vue.prototype.$bus = new Vue();
(2)作为js模块
//moduleEvent.js
import Vue from 'vue'
export default new Vue()
// main.js 引入
import moduleEvent from './assets/moduleEvent';
Vue.prototype.$bus = moduleEvent;
(3)作为vue模块
// moduleEvent.vue
<tempalte>
</template>
<script>
import Vue from 'vue';
export default new Vue({
data () {
}
})
</script>
// main.js
import moduleEvent from './assets/moduleEvent';
Vue.prototype.$bus = moduleEvent;
2、使用事件总线
// moduleA.vue
methods: {
sendData () {
// 通过修改Vue原型链的方式注册
this.$bus.$emit('test', this.dataA);
// 直接注册在window上
// moduleEvent.$emit('test', this.dataA);
}
}
// moduleB.vue
methods: {
getData () {
// 通过修改Vue原型链的方式注册
this.$bus.$on('test', function (data) {
// handle data code
// 回调函数的参数data即为组件A传递的值
});
// 直接注册在window上
// moduleEvent.$on('test', function (data) {
// handle data code
// 回调函数的参数data即为组件A传递的值
// });
}
}
3、单次接收事件或者移除事件Listeners
如果你只想监听一次该事件。可以使用 this.$event.$once(channel: string, callback(payload1, payload2, ...)),事件触发一次后将移除事件。
如果你想移除自定义事件监听器,你可以使用 this.$event.$off([event, callback]); 来实现。该方法如果没有提供参数,则移除所有的事件监听器;如果只提供事件,则移除该事件所有的监听器;如果同时提供了事件与回调,则只移除这个回调的监听器。
4、路由传参是否可以使用事件总线呢?那样的话地址栏就不会暴漏id和参数了,我测试了一下发现不行,因为跳转之前就调用了$emit事件,此时路由还没加载没法监听到,只能乖乖的使用vue-router提供的传参方式。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。