[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信

全局事件总线原理分析

前提:x是个组件,不属于任何一个组件

要求:A组件想要收到别的组件给的信息

在A组件里给x绑定个自定义事件demo,对应的回调函数就留在A中
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第1张图片
D组件想给A传点数据,就可以这样做:
在D组件里,写点代码触发x身上的demo事件,并且传点数据过去(666),
x身上的demo事件被触发了,demo事件的回调函数就得执行,而这个回调函数在A组件里面,那之前D组件传的数据666,就在A组件里面
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第2张图片

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第3张图片

要求:B组件想收到点别的组件传的数据,

在B组件里写点代码,给x组件绑定个事件test,回调函数留在B组件中
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第4张图片
当D组件给B组件传数据时,
在D组件中写点代码,触发x组件身上的test事件,带个数据8过去,
那D组件身上的test事件就会被触发,那test事件所对应的回调就会被执行,而这个回调函数在B中,B就会接收到test事件携带的数据8
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第5张图片
整个应用里,各种绑定事件,触发事件,都靠x组件,
以上就是事件总线的原理图

要求:

  1. 所有人都能看到x

  2. x能调用$on,绑定自定义事件
    x能调用$off,解绑事件
    x能调用$emit,触发事件

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第6张图片

1. 所有人都能看到x

所有组件都能看到x组件

直接把x加到vue的原型上就好了,因为VueComponent.prototype.__proto__ === Vue.prototype,把x加到vue的原型上,VC的实例也能访问到,组件也能访问到
[vue] 一个重要的内置关系 VueComponent.prototype.proto === Vue.prototype
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第7张图片
举例:
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第8张图片
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第9张图片

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第10张图片
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第11张图片

2. x能调用$on,$off,$emit

$on,$off,$emit在Vue的Prototype上

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第12张图片

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第13张图片
x想使用Vue原型上的这三个方法,x要么是vm(vue实例对象),要么是vc(组件实例对象)

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第14张图片
d就是vc,就可以调用到$on,$off,$emit

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第15张图片
[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第16张图片

在这里插入图片描述

这样就简单实现了Student给School传递数据,兄弟组件可以通信了

[vue] 全局事件总线 this.$bus.$emit this.$bus.$on ,可以实现任意组件间通信_第17张图片
一般来说,不叫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   // 安装全局事件总线
    }
})

全局事件总线总结

  1. 一种组件间通信的方式,适用于任意组件间通信。

  2. 安装全局事件总线:
    main.js

    new Vue({
        el:'#app',
        render:h=>h(App),
        beforeCreate () {
            // this就是Vue实例对象vm   ,vm上有$on,$emit,$off,直接用它就行
            Vue.prototype.$bus = this   // 安装全局事件总线
        }
    })
    
  3. 使用事件总线:

    1. 接收数据:
      在School组件的生命周期钩子中添加事件到事件总线($bus)上 回调留在留在School组件自身

    2. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

        mounted () {
    		// 给$bus绑定个自定义事件hello,回调函数在School组件里
    		this.$bus.$on('hello',(data)=>{
    			console.log('我是School组件,我收到了数据:',data);
    			
    		})
    	},
    	// 在销毁前解绑$bus
    	beforeDestroy () {
    		this.$bus.off('hello')
    	}
    
    1. Student组件提供数据:
    	<button @click="SendStudentName">把Student数据给Schoolbutton>
    
    	methods: {
    		SendStudentName(){
    			// 触发$bus身上的自定义事件hello,并传个数据过去
    			this.$bus.$emit('hello',666)
    		}
    	}
    




参考:
尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通

你可能感兴趣的:(#,vue,vue.js)