全局事件总线的作用

全局事件总线︰可以实现任意组件间通信。

全局事件总线的设计思路

设计一个不属于任何组件的东西 通过自定义事件 来帮我们实现任意组件间通信。
当组件想要接收数据时在X上绑定自定义事件,编写事件回调函数。
当组件想要传递数据是去触发X上的事件,可以携带参数。
在这里插入图片描述

X

不属于任何组件的X应该满足的条件:

  • 保证所有组件都可以看到x
  • x可以调用到 $on 进行事件绑定
  • x可以调用到 $emit 进行事件触发
  • 当然也可以访问到 $off 进行事件解绑

x放在哪

为保证所有组件都可以看到x,可以将x放在Vue的原型对象上。
我们知道:VueComponent.prototype._proto_ === Vue.prototype.,所以所有的组件实例对象都可以通过原型链找到Vue原型对象上的内容。
在这里插入图片描述
在main.js中添加如下语句

Vue.prototype.x = {}

让X可以调用: $on$emit$off

在组件实例对象上可以直接调用 $on$emit$off,是因为 $on$emit$offvue的原型对象上,所以想要x可以调用 $on$emit$off需要将赋值为vc(组件实例对象)或 vm(vue实例对象)。

  • 组件实例对象的写法:
    main.js
const Demo = Vue.extend({})
// 平常组件实例化是靠我们声明组件标签,vue帮我们实例化,但是这里不能声明直接使用new‘就可
const demo = new Demo()

Vue.prototype.x = demo 
  • vue实例对象(vm)写法:
    在vue的beforeCreate中编写。
    main.js
new Vue({
  el:"#root",
  render: h => h(App),
  beforeCreate() {
    Vue.prototype.x = this//安装全局事件总线
  }
})

我们一般将x命名为:$bus

所以创建全局事件总线最常用的写法,如下

// 创建vue实例对象
new Vue({
  el:"#root",
  render: h => h(App),
  beforeCreate() {
    Vue.prototype.$bus = this//安装全局事件总线
  }
})

例子

School接收数据,Student组件发送数据。

  • School组件使用$on进行事件的绑定,编写回调函数,并且用完之后最好使用$off解绑一下
  • Student组件使用$emit进行事件的触发
    main.js:
/**
 * 该文件是整个项目的入口文件
 */

// 引入vue
import Vue from 'vue'
// 引入App
import App from './App.vue'
// 关闭vue生产提示
Vue.config.productionTip = false


// 创建vue实例对象
new Vue({
  el:"#root",
  render: h => h(App),
  beforeCreate() {
    Vue.prototype.$bus = this
  }
})

School.vue:

<template>
    <div class="demo">
        <h2>学校名字:{{ name }}</h2>
        <h2 class="fonty">地址:{{ address }}</h2>
        <hr>
    </div>
</template>

<script>
export default {
    name: 'SchoolVue',
    data() {
        return {
            name: "nefu",
            address: "哈尔滨",
        };
    },
    mounted() {
        // 绑定事件,编写回调函数
        this.$bus.$on('hello', (data) => {
            console.log('我是school组件,我接受到了数据:', data)
        })
    },
    beforeDestroy() {
        // 该组件销毁时记得解绑,避免占用$bus的资源
        this.$bus.off('hello')
    }
}
</script>
<style scoped lang="less">
.demo{
    background: skyblue;
}
</style>

Student.vue:

<template>
    <div class="demo">
        <h2>名字:{{ name}}</h2>
        <h2>性别:{{ sex }}</h2>
        <button @click="sendStudentName">把学生姓名给school</button>
        <hr>
    </div>
</template>
<script>
export default {
    name:'StudentVue',
    data() {
        console.log(this)
        return {
            name:"yang123",
            sex:"男"
        }
    },
    methods: {
        sendStudentName() {
            // 触发事件
            this.$bus.$emit('hello',this.name)
        }
    }
}

</script>
<style scoped>
.demo{
    background: lightsalmon;
}
</style>

在这里插入图片描述

全局事件总线的本质

全局事件总线的本质就是使用自定义事件

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐