首页 > 编程笔记

Vue事件总线用法详解

在 Vue.js 中实现组件之间数据的传递,大概有以下几种方式:
还可以使用事件总线的方式和 Vuex 的 state 的属性实现任意组件之间的数据共享。接下来介绍 Vue.js 中的事件总线,并用它实现组件之间的数据共享传递。

Vue事件总线

事件总线又称为 EventBus,在 Vue.js 中可以使用 EventBus 来作为沟通的桥梁,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但由于太方便,若使用不慎,就会造成难以维护的灾难(所以由 Vuex 作为管理状态中心,将通知的概念提升为状态共享)。

使用事件总线,可以分三步实现。

1) 注册事件总线

创建一个全局的 Vue.js 对象,用来充当事件总线中心,以及用来传递事件。该事件总线只能用在当前页面的组件中,也可以将这个 Vue.js 对象保存到 Vue.js 的原型属性中,从而注册一个全局的事件总线中心,代码如下:
// 创建事件总线 
const eventBus = new Vue(); 
// 注册全局事件中心 
Vue.prototype.$bus = eventBus;

2) 接收事件总线

定义一个组件,使用 $on(事件名称,回调函数)方法,给指定的总线事件绑定一个函数,监听事件总线中的事件,代码如下: 
<!-- 第1个组件模板,显示age --> 
<template id="my-view1"> 
    <div>View1 age: {{ age }}</div> 
</template> 
 
<script type="text/javascript"> 
// 创建MyView1对象 
const MyView1 = { 
    data() { 
        return { 
            age: 1 
        }; 
    }, 
    mounted() { 
        // 监听bus总线中的bindEvent事件 
        eventBus.$on('bindEvent', user => { 
            this.age = user.age + this.age; 
        }); 
    }, 
    template: '#my-view1' 
}; 
...
</script>
...

3) 发送事件总线

在组件代码中,用$emit(事件名称,参数)方法,向事件总线中心发送一个事件,并传递参数内容,代码如下:
... 
<script type="text/javascript"> 
...
const vm = new Vue({ 
    ...
    methods: { 
        publishEvent() { 
            this.value++; // 增加value的值 
            // 往eventBus总线发布bindEvent事件(全局) 
            // 使用正确的事件名(字符串形式,并且没有感叹号) 
            // 传递一个对象作为事件的参数 
            eventBus.$emit('bindEvent1', { name: 'zhangsan', age: this.value }); 
        } 
    } 
}); 
</script> 
...
整合后的代码如下:
...
<div id="app"> 
    <my-view1></my-view1> 
    <my-view2></my-view2> 
    <button @click="publishEvent">测试</button> 
</div> 
 
<!-- 第1个组件模板,显示age --> 
<template id="my-view1"> 
    <div>View1 age: {{ age }}</div> 
</template> 
 
<!-- 第2个组件模板,显示age --> 
<template id="my-view2"> 
    <div>View2 age: {{ age }}</div> 
</template> 

//事件总线
const eventBus = new Vue()

<script type="text/javascript"> 
// 创建MyView1对象 
const MyView1 = { 
    data() { 
        return { 
            age: 1 
        }; 
    }, 
    mounted() { 
        // 监听bus总线中的bindEvent事件 
        eventBus.$on('bindEvent', user => { 
            this.age = user.age + this.age; 
        }); 
    }, 
    template: '#my-view1' 
}; 
 
// 创建MyView2对象 
const MyView2 = { 
    data() { 
        return { 
            age: 10 
        }; 
    }, 
    mounted() { 
        // 监听bus总线中的bindEvent事件 
        eventBus.$on('bindEvent', user => { 
            this.age += user.age; 
        }); 
    }, 
    template: '#my-view2' 
}; 

// 创建Vue实例并挂载到页面元素上 
const vm = new Vue({ 
    el: '#app', 
    data: { 
        value: 1 
    }, 
    components: { 
        MyView1, 
        MyView2 
    }, 
    methods: { 
        publishEvent() { 
            this.value++; 
            // 往bus总线发布bindEvent事件 
            eventBus.$emit('bindEvent', { name: 'zhangsan', age: this.value }); 
        } 
    } 
}); 
</script> 
...

推荐阅读