大家都知道,一个
,可以作为一个简单的组件传递数据,用于解决跨级和兄弟组件通信问题,那么,这篇文字,我将使用这种思想,将bus封装为一个Vue的插件,可以在所有的组件间任意使用,而不需要导入bus。
首先,我们使用vue-cli创建一个项目vue-bus, 在src目录下,新建vue-bus.js文件,vue-bus插件像vue-router 和 Vuex一样,给Vue对象添加一个属性$bus,并代理$emit、$on、$off三个方法。代码如下:
const install = (Vue)=>{
const Bus = new Vue({
methods:{
emit(event,...args){
this.$emit(event,...args)
},
on(event,...args){
this.$on(event,...args)
},
off(event,...args){
this.$off(event,...args)
}
}
})
Vue.prototype.$bus = Bus;
}
export default install
在main.js中使用插件,代码如下:
import Vue from "vue";
// import App from "./App.vue";
// import router from "./router";
// import store from "./store";
// import axios from "axios";
import VueBus from './vue-bus';
Vue.use(VueBus);
接下来,在views目录下,新建一个组件 Counter.vue,代码如下:
<template>
<div class="counter">
<button @click="randomAddHandler">randomAddHandler</button>
</div>
</template>
<script>
export default {
name: "counter",
props: ["number"],
methods: {
randomAddHandler() {
var num = Math.floor(Math.random() * 100);
this.$bus.emit("getRandomNum", num);
}
}
};
</script>
在它的非父子组件中使用。
<template>
<div class="child">
{{number}}
<input type="text" v-model="$attrs.messageC" @input="setCData($attrs.messageC)">
</div>
</template>
<script>
export default {
name:'child',
data(){
return{
number:''
}
},
created(){
this.$bus.on('getRandomNum',val=>{
this.number = val;
})
},
beforeDestroy(){
this.$bus.off('getRandomNum')
},
methods:{
setCData(val){
this.$emit('getCData',val)
}
}
}
</script>
note!
使用vue-bus有两点需要注意,第一是$bus.on应该在created钩子内使用,如果在mounted使用,它可能接收不到其他组件来自created钩子内发出的事件;第二点是使用了$bus.on在beforeDestory钩子里应该需要使用$bus.off解除,因为组件销毁后,就没有必要把监听的句柄存储在vue-bus里面了