全局事件总线原理分析
前提:x是个组件,不属于任何一个组件
要求:A组件想要收到别的组件给的信息
在A组件里给x绑定个自定义事件demo,对应的回调函数就留在A中
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js](https://file.cfanz.cn/uploads/png/2022/12/21/3/M6W9Q5dYb9.png)
D组件想给A传点数据,就可以这样做:
在D组件里,写点代码触发x身上的demo事件,并且传点数据过去(666),
x身上的demo事件被触发了,demo事件的回调函数就得执行,而这个回调函数在A组件里面,那之前D组件传的数据666,就在A组件里面
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js_02](https://file.cfanz.cn/uploads/png/2022/12/21/3/b8H1e221e6.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_Vue_03](https://file.cfanz.cn/uploads/png/2022/12/21/3/J4YE79P9ea.png)
要求:B组件想收到点别的组件传的数据,
在B组件里写点代码,给x组件绑定个事件test,回调函数留在B组件中
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_Vue_04](https://file.cfanz.cn/uploads/png/2022/12/21/3/9F405bc5Z6.png)
当D组件给B组件传数据时,
在D组件中写点代码,触发x组件身上的test事件,带个数据8过去,
那D组件身上的test事件就会被触发,那test事件所对应的回调就会被执行,而这个回调函数在B中,B就会接收到test事件携带的数据8
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js_05](https://file.cfanz.cn/uploads/png/2022/12/21/3/b3QV1N067R.png)
整个应用里,各种绑定事件,触发事件,都靠x组件,
以上就是事件总线的原理图
要求:
- 所有人都能看到x
- x能调用
$on,绑定自定义事件
x能调用$off,解绑事件
x能调用$emit,触发事件
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js_06](https://file.cfanz.cn/uploads/png/2022/12/21/3/15a60IJ0XT.png)
1. 所有人都能看到x
所有组件都能看到x组件
直接把x加到vue的原型上就好了,因为VueComponent.prototype.__proto__ === Vue.prototype,把x加到vue的原型上,VC的实例也能访问到,组件也能访问到
[vue] 一个重要的内置关系 VueComponent.prototype.proto === Vue.prototype
![加载vue [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js_07](https://file.cfanz.cn/uploads/png/2022/12/21/3/5097RBS481.png)
举例:
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_事件总线_08](https://file.cfanz.cn/uploads/png/2022/12/21/3/BYWY5c119c.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_Vue_09](https://file.cfanz.cn/uploads/png/2022/12/21/3/E2KX9662U5.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js_10](https://file.cfanz.cn/uploads/png/2022/12/21/3/174B9b42K0.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_事件总线_11](https://file.cfanz.cn/uploads/png/2022/12/21/3/86406dGdTU.png)
2. x能调用$on,$off,$emit
$on,$off,$emit在Vue的Prototype上
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_Vue_12](https://file.cfanz.cn/uploads/png/2022/12/21/3/36GS1Q509c.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_App_13](https://file.cfanz.cn/uploads/png/2022/12/21/3/36J13R1a98.png)
x想使用Vue原型上的这三个方法,x要么是vm(vue实例对象),要么是vc(组件实例对象)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_App_14](https://file.cfanz.cn/uploads/png/2022/12/21/3/0L5113P955.png)
d就是vc,就可以调用到$on,$off,$emit
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_App_15](https://file.cfanz.cn/uploads/png/2022/12/21/3/EPR546034R.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_Vue_16](https://file.cfanz.cn/uploads/png/2022/12/21/3/I4c8493c02.png)
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_vue.js_17](https://file.cfanz.cn/uploads/png/2022/12/21/3/2Z3A9T059M.png)
这样就简单实现了Student给School传递数据,兄弟组件可以通信了
![在这里插入图片描述 [vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_Vue_18](https://file.cfanz.cn/uploads/png/2022/12/21/3/W6CIM0H6eZ.png)
一般来说,不叫x,叫$bus
安装全局事件总线
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// VueRouter引入到Vue类中
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
el:'#app',
render:h=>h(App),
beforeCreate () {
// this就是Vue实例对象vm ,vm上有$on,$emit,$off,直接用它就行
Vue.prototype.$bus = this // 安装全局事件总线
}
})
代码
Student.vue
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="SendStudentName">把Student数据给School</button>
</div>
</template>
<script>
export default {
name:'Student',
data() {
return {
name:'张三',
sex:'男',
number:0
}
},
methods: {
SendStudentName(){
// 触发x组件身上的自定义事件hello,并传个数据过去
this.$bus.$emit('hello',666)
}
}
}
</script>
<style scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
School.vue
<template>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>
<script>
export default {
name:'School',
data() {
return {
name:'尚硅谷',
address:'北京',
}
},
// // School组件只要挂载完毕,马上给$bus绑定个自定义事件hello
mounted () {
// 给$bus绑定个自定义事件hello,回调函数在School组件里
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,我收到了数据:',data);
})
},
// 在销毁前解绑$bus
beforeDestroy () {
this.$bus.off('hello')
}
}
</script>
<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
</style>
App.vue
<template>
<div class="app">
<h1>{{msg}}</h1>
<School></School>
<Student></Student>
</div>
</template>
<script>
import Student from './components/Student'
import School from './components/School'
export default {
name:'App',
components:{School,Student},
data() {
return {
msg:'你好啊!',
}
},
}
</script>
<style scoped>
.app{
background-color: gray;
padding: 5px;
}
</style>
main.js
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
// VueRouter引入到Vue类中
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
el:'#app',
render:h=>h(App),
beforeCreate () {
// this就是Vue实例对象vm ,vm上有$on,$emit,$off,直接用它就行
Vue.prototype.$bus = this // 安装全局事件总线
}
})
全局事件总线总结
- 一种组件间通信的方式,适用于任意组件间通信。
- 安装全局事件总线:
main.js
new Vue({
el:'#app',
render:h=>h(App),
beforeCreate () {
// this就是Vue实例对象vm ,vm上有$on,$emit,$off,直接用它就行
Vue.prototype.$bus = this // 安装全局事件总线
}
})- 使用事件总线:
- 接收数据:
在School组件的生命周期钩子中添加事件到事件总线($bus)上 回调留在留在School组件自身 - 最好在beforeDestroy钩子中,用
$off去解绑当前组件所用到的事件
mounted () {
// 给$bus绑定个自定义事件hello,回调函数在School组件里
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,我收到了数据:',data);
})
},
// 在销毁前解绑$bus
beforeDestroy () {
this.$bus.off('hello')
}- Student组件提供数据:
<button @click="SendStudentName">把Student数据给School</button>
methods: {
SendStudentName(){
// 触发$bus身上的自定义事件hello,并传个数据过去
this.$bus.$emit('hello',666)
}
}参考:
尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通










