每天进步一点点(2020.05.20)--事件总线

1,681 阅读1分钟

事件总线 EventBus

Vue官方推荐的组件之间的的通信是使用状态管理工具Vuex;但是当我们项目不大,通信不复杂使得项目中不值得使用Vuex的时候;我们可以使用今天的主角 EventBus;

原理

new Vue()创建一个不包含dom的vue实例对象;由于 Vue 实例实现了一个事件分发接口;你可以在需要通讯的组件中引入此实例,然后利用此实例对象的实例方法 $on,$off,$emit方法来进行通讯。

  • vm.$on( event, callback ) 监听当前实例上的自定义事件。事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。

  • vm.$off( [event, callback] ) 移除自定义事件监听器。

    1. 如果没有提供参数,则移除所有的事件监听器;

    2. 如果只提供了事件,则移除该事件所有的监听器;

    3. 如果同时提供了事件与回调,则只移除这个回调的监听器。

  • vm.$emit( eventName, […args] ) 触发当前实例上的事件。附加参数都会传给监听器回调。

全局事件总线

// main.js

1. Vue.prototype.$eventBus = new Vue();

// 或者
2. var eventBus = {
    install(Vue, options) {
        Vue.prototype.$eventBus = vue;
    }
};
Vue.use(eventBus);
使用
// A 组件
methods: {
    todo() {
        //...
        this.$eventBus.$emit('todoSth', params);  //params是传递的参数
    }
}
// B 组件
created() {
    this.$eventBus.$on('todoSth', (params) => {  //获取传递的参数并进行操作
        //todo something
    })
},

// 在组件销毁前 清除事件监听
beforeDestroy () {
    this.$eventBus.$off('todoSth');
}

组件内的事件总线

// src/assets/event-bus.js
import Vue from 'vue'
export const eventBus = new Vue();
使用
// A 组件
<script>
import { eventBus } from "@/assets/event-bus.js";
export default {
    methods: {
        todo() {
            //...
            eventBus.$emit('todoSth', params);  //params是传递的参数
        }
    } 
}
</script>
// B 组件
<script>
import { eventBus } from "@/assets/event-bus.js";
export default {
    created() {
        eventBus.$on('todoSth', (params) => {  //获取传递的参数并进行操作
            //todo something
        })
    },
    
    // 在组件销毁前 清除事件监听
    beforeDestroy () {
        eventBus.$off('todoSth');
    }
}

注意点

  1. 为什么第一次触发的时候页面B中的on事件没有被触发?
    原因:A页面$emit的时候,B页面还没生成导致$on还没触发监听;所以要确保组件A,B组件同时存在;
  2. 每一次的事件触发执行越来越多?
    原因:$on事件是不会自动清楚销毁的,需要我们手动来销毁;

参考资料

vue篇之事件总线
中央事件总线传值及遇见的坑
Vue事件总线(EventBus)使用详细介绍


再长的路,一步步也能走完,再短的路,不迈开双脚也无法到达。