在原型中注册 全局事件总线
在一个脚手架搭建的vue项目中的main.js文件中:
new Vue({
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus = this
// 往Vue的原型上放一个 全局事件总线 $bus(可以任意命名,但是约定俗成用$bus),
// 在子组件VueComponent中就能调用到这个原型里的东西,因为子组件原型会往Vue的原型上面找
}
}).$mount('#app')
在生命周期函数中注册 事件
在App.vue的mounted钩子函数中注册好自定义事件
mounted(){
this.$bus.$on('事件1',this.methods中的方法)
this.$bus.$on('事件2',xxxx(这部分也可以写回调函数,但是得用箭头函数))
},
调用 全局事件总线中的 事件
在需要用到自定义事件的子组件中,用$emit 调用自定义事件,有参传参。
methods: {
fn(){
this.$bus.$emit('事件名')
},
},
注意:兄弟组件之间通信,如果一个把事件定义在mounted,一个调用在mounted,会受到App中的先后的引用顺序影响,如果先调用的子组件在前,定义的子组件在后,则不起效果。
注销事件
在App.vue的beforeDestroy钩子函数中写好注销自定义事件:
beforeDestroy() { // 绑在$bus上的 都要主动销毁,因为App.vue销毁之后,$bus还在,在上面注册的事件都还在占空间,所以销毁时得一起$off掉
this.$bus.$off(['事件1','事件2']) // 同时关闭多个用数组形式放进去
}
注意:绑在 $ bus上的 都要主动销毁,因为App.vue销毁之后,$ bus还在,在上面注册的事件都还在占有空间,所以销毁vue时得一起把全局事件总线销毁掉
综上例子
掌握理论,开始实践
App.vue:
<template>
<div>
<!-- 子组件 -->
<Test></Test>
</div>
</template>
<script>
import Test from "./components/Test.vue"
export default {
components: {
Test // 子组件
},
methods: {
testFn(arg){
console.log("testBus1事件触发,函数被调用,参数:",arg);
}
}
mounted(){
this.$bus.$on('testBus1',this.testFn)
this.$bus.$on('testBus2',(arg)=>{
console.log("testBus2事件回调函数被调用,参数:",arg);
})
}
}
</script>
子组件 Test.vue
<template>
<div>
<button @click="emitBus1" >触发testBus1事件</button>
<button @click="emitBus2">触发testBus2事件</button>
<button @click="destoryBus">销毁事件</button>
</div>
</template>
<script>
export default {
name:"Test",
data(){
return{
testData:'test'
}
},
methods:{
emitBus1(){
this.$bus.$emit('testBus1','test1') // 第二个及往后都是传递的参数
},
emitBus2(){
this.$bus.$emit('testBus2','test2')
},
destoryBus(){
this.$bus.$off(['testBus1','testBus2'])
}
}
}
</script>
效果: