vue-bus
一个 Vue.js 事件中心插件,同时支持 Vue 1.0 和 2.0
原因
Vue 2.0 重新梳理了事件系统,因为基于组件树结构的事件流方式实在是让人难以理解,并且在组件结构扩展的过程中会变得越来越脆弱。虽然依然保留了父子组件间的事件流,但有诸多限制,比如不支持跨多层父子组件通信,也没有解决兄弟组件间的通信问题。
Vue 推荐使用一个全局事件中心来分发和管理应用内的所有事件,详见文档。这是一个最佳实践,同时适用于 Vue 1.0 和 2.0。你当然可以声明一个全局变量来使用事件中心,但你如果在使用 webpack 之类的模块系统,这显然不合适。每次使用都手动 import 进来也很不方便,所以就有了这个插件:vue-bus
vue-bus 提供了一个全局事件中心,并将其注入每一个组件,你可以像使用内置事件流一样方便的使用全局事件。
安装
$ npm install vue-bus
如果在一个模块化工程中使用它,必须要通过 Vue.use()
明确地安装 vue-bus:
-
import Vue from 'vue';
-
import VueBus from 'vue-bus';
-
Vue.use(VueBus);
如果使用全局的 script 标签,则无须如此(手动安装)。
使用
监听事件和清除监听
-
// ...
-
created() {
-
this.$bus.on('add-todo', this.addTodo);
-
this.$bus.once('once', () => console.log('这个监听器只会触发一次'));
-
},
-
beforeDestroy() {
-
this.$bus.off('add-todo', this.addTodo);
-
},
-
methods: {
-
addTodo(newTodo) {
-
this.todos.push(newTodo);
-
}
-
}
触发事件
-
// ...
-
methods: {
-
addTodo() {
-
this.$bus.emit('add-todo', { text: this.newTodoText });
-
this.$bus.emit('once');
-
this.newTodoText = '';
-
}
-
}
注意:$bus.on
$bus.once
$bus.off
$bus.emit
只是 $bus.$on
$bus.$once
$bus.$off
$bus.$emit
的别名。 详见 API。
==========================================================
vue 事件总线问题
问题一: 不同组件传值(非父子组件)
在main.js中,构建
eventBus = new Vue();
pageA.vue
在methods中发布事件
eventBus.$emit('test', 123);
应该在pageB.vue生命周期creatd/mounted中触发事件,
eventBus.$on('test', (content) => {
//content即是出过来的值
});
问题二: 跳转路由
pageA.vue在methods中进行路由跳转,这时候就应在该组件被销毁之前触发:
beforeDestroy (){
eventBus.$emit('testClick', this.msg);
},
pageB.vue:应该在pageB.vue生命周期creatd/mounted中触发事件,
eventBus.$on('testClick', val => {
console.log(val)
});
不要忘记清除事件(要不会触发多次);
beforeDestroy() {
eventBus.$off('testClick')
},
=======================================================================
1.组件通讯
父子组件之间传递数据子组件通过
props
来接受父组件传递的数据,在兄弟组件之间传递数据的话可以使用框架vuex
,对于不是庞大的单页面应用就不太适合使用了, vue 官网提供了一种方法叫做 中央事件总线
-
// 新建一个 Bus.vue文件,new 一个 vue 实例导出
-
export default new Vue({
-
name: 'bus',
-
data () {
-
return {
-
// code
-
}
-
}
-
})
-
// 可以理解为这是一个传话人员
-
// 新建一个组件 A
-
<tempalte>
-
<button @click="sendMessage"向组件 B 发送数据</button>
-
</tempalte>
-
<script>
-
import Bus from 'Bus.vue'
-
export default {
-
name: 'componentA',
-
data () {
-
return {
-
msg: 'the message is from componentA'
-
}
-
},
-
methods: {
-
sendMessage () {
-
// 假设知道组件 B 有个方法叫做 inceptMessage(接收数据的方法)
-
// 组件 A对组件 B 说 我要通过 Bus 这个传话员给你传话了,你先告诉我
-
// 这么理解,当组件 A 通过 Bus 传话员去触发inceptMessage这个方法的时候,组件 B 是可以感应到组件 A 调用了这个方法的
-
Bus.$emit('inceptMessage', this.msg)
-
// Bus 通过触发组件 B 的inceptMessage方法将 msg 发送过去了,这个时候组件 B 还不知道组件 A 给它发送了一条数据
-
}
-
}
-
}
-
</script>
-
// 新建一个组件 B
-
<tempalte>
-
// 显示组件 A 传过来的数据
-
<h1>{{ fromComponentAMsg }}</h1>
-
</tempalte>
-
<script>
-
import Bus from 'Bus.vue'
-
export default {
-
name: 'componentB',
-
data () {
-
return {
-
fromComponentAMsg: ''
-
}
-
},
-
methods: {
-
},
-
mounted () {
-
// 这个时候组件 B 知道组件 A 给它传了一条数据过来了,于是赶紧叫 Bus 这个传话员把数据告诉它
-
// bus 就告诉组件 B, 组件 A 那边通过inceptMessage传过来一条数据叫 msg
-
Bus.$on('inceptMessage',(msg) => {
-
this.fromComponentAMsg = msg
-
})
-
}
-
}
-
</script>
2 . 组件前进刷新,后退不刷新
vue 官网给出的一个方法是通过
keep-alive
将router-view
包住就能实现组件不刷新显示原来的数据,但是在组件中一般都是前进更新数据返回的时候不刷新保留原来的数据,增加用户体验,通过搜索发现了一个方法
-
export default {
-
name: 'xxx',
-
data () {
-
//...
-
},
-
deactivated () {
-
this.$destroy()
-
},
-
methods: {
-
// ...
-
}
-
}