初学Vue
全局事件总线
1、功能
实现任意组件间通信
2、图示
拿兄弟组件之间的通信来举例,Son2传递数据给Son1,如下:
分析如下:
在Son1中自定义一个事件并绑定回调函数(@demo=“function”),将这个事件(demo)交给全局事件总线,Son2利用全局事件总线,触发demo事件,随即demo事件调用回调函数。
很好理解,就是全局事件总线是个工具人,别人叫它干什么就干什么,它可以让所有的组件都能够使用上面的事件,那么问题来了,它位于什么上?vueComponent.prototype?不是。所有的组件都是通过vueComponennt构造函数创建出来的,但每次调用Vue.extend时返回的都是一个新的VueComponent,不好管理。
注意,有这么一个内置关系vueComponent.prototype._proto_===Vue.prototype,用于让组件实例对象vc可以访问Vue原型上的属性和方法,由此知道可以将这个全局事件总线放在Vue的原型对象上。
通常用$bus来表示全局事件总线。
3、使用步骤
1、安装事件总线
new Vue({
beforeCreate(){
Vue.prototype.$bus = this
// this指的就是当前实例对象vm,也就是说$bus这个事件总线就是vm
}
});
2、使用事件总线
(1)接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
demo(data){
......}
}
....
mounted(){
this.$bus.$on('xxx',this.demo)
}
(2)提供数据:this.$bus.$emit('xxx',数据)
(3)并且最好在new Vue()中使用beforeDestroy钩子,用$off去解绑当前组件中所用到的事件。
4、使用案例
有两个兄弟组件School.vue和Student.vue,让Student组件往School组件上传递数据。
- main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
// 安装全局事件总线
beforeCreate(){
Vue.prototype.$bus=this // this指的是当前对象vm
}
}).$mount('#app')
- App.vue
<template>
<div id="app">
<School></School>
<Student></Student>
</div>
</template>
<script>
import School from "./components/School.vue"
import Student from "./components/Student.vue"
export default {
name:"App",
components:{
School,Student},
}
</script>
<style>
#app{
background-color: grey;
}
</style>
- School.vue
<template>
<div class="school">
<h3>学校名称:{
{name}}</h3>
<h3>学校地址{
{address}}</h3>
<!-- <button>点我把数据传给Student组件</button> -->
</div>
</template>
<script>
export default {
name:"School",
data(){
return {
name:"清华大学",
address:"北京"
}
},
mounted(){
// 将School组件上的event1事件通过$on放到全局事件总线$bus上
this.$bus.$on("event1",(data)=>{
console.log("我是School组件,收到了数据",data);
// 回调要使用箭头函数的形式,这里的this指向函数绑定的对象,这里也就是School组件的vc
})
}
}
</script>
<style>
.school{
background-color: lightgreen;
}
</style>
- Student.vue
<template>
<div class="student">
<h3>学生姓名:{
{name}}</h3>
<h3>学生年龄:{
{age}}</h3>
<button @click="sendMsgToSchool">点我把数据传给School组件</button>
</div>
</template>
<script>
export default {
name:"Student",
data(){
return {
name:"张三",
age:21
}
},
methods:{
// 触发click事件后调用该方法
sendMsgToSchool(){
// 通过this使用全局事件总线$bus,再通过$emit触发总线上指定的事件
this.$bus.$emit("event1",this.name);
}
}
}
</script>
<style>
.student{
background-color: pink;
}
</style>