EventBus 称事件总线,在 vue 项目中作为沟通桥梁的概念,就像所有组件公用相同的事件中心,可以向该中心注册发送事件或接收事件。
使用场景:
项目中假设资产信息管理中有不同类别的资产模块,我们需要在页面中多次调用不同类别的资产查看资产详情页面。可以使用 事件总线,封装一个详情弹框组件,通过 类别名和类别 id 调出对应的详情组件。
在 main.js
中初始化事件总线,使用两个方法 $on
和 $emit
,$emit
用于创建发出的事件,$on
用于订阅。
src/main.js
// 1、创建一个全局的事件总线
Vue.prototype.$bus = new Vue()
创建好了 EventBus
,接下来在组件中加载它,并调用同一个方法,如同在父子组件中互相传递消息。
构建详情组件AssetsDetail.vue
组件
<template>
<el-dialog
:visible.sync="visible"
:before-close="onClose"
width="900px">
<component :is="curComp" :id="id"></component>
</el-dialog>
</template>
<script>
export default {
props: {
curComp: {
type: String,
default: ''
},
id: Number
},
components: {
device: () => import('@/main/components/basis/device/DeviceDetail'),
person: () => import('@/main/components/basis/person/PersonDetail'),
},
data() {
return {
visible: true
}
},
methods: {
onClose() {
this.$emit('update:curComp', '') // 2、发布事件
}
}
}
</script>
<style lang="less" scoped>
/deep/ .el-dialog__body {
height: 500px;
}
</style>
注意:在命名事件名称的时候,我们最好在一个配置文件中定义好一个事件变量名,然后导出这个事件变量名。
config.js
// 详情组件字段名
let DETAIL = 'detail'
export default {
DETAIL
}
DeviceList.vue
在 device
和 person
的列表组件中查看对应的详情
...
import config from '@/assets/scripts/config'
...
goDetail(row) {
this.$bus.$emit(config.DETAIL, 'device', row.id)
}
PersonList.vue
...
import config from '@/assets/scripts/config'
...
// 查看人员详情
lookPersonInfoClick(row) {
this.title = '详情'
this.$bus.$emit(config.DETAIL, 'person', row.id) // 发布事件
}
在 App.vue
中接收刚才发出的事件,并添加刚才封装好的 详情组件。因为我们的 Vue 是单页面的,加载每个组件都会经过 App.vue
,App.vue
就相当于我们的父组件,其他子组件中就可以正常使用 事件总线了
App.vue
<template>
<div id="page-main">
<router-view class="router-view" />
<assets-detail :curComp.sync="component" :id="id" v-if="component !== ''" />
</div>
</template>
<script>
import AssetsDetail from '@/main/components/AssetsDetail'
import config from '@/assets/scripts/config'
export default {
components: {
AssetsDetail
},
data() {
return {
component: '',
id: null
}
},
created () {
this.$bus.$on(config.DETAIL, (type, id) => { // 3、订阅事件
this.component = type
this.id = id
})
},
beforeDestroy() {
this.$bus.$off(config.DETAIL) // 4、结束事件
}
}
</script>
这样我们就能在不同的组件中调用不同类别的详情组件了