Vue:事件Bus在手 天下我有~

事件Bus在手 天下我有~

事件Bus是什么 ?

它是一个Vue实例 , 用作一个组件内或者页面内的事件中心总线 , 帮助组件内通信
Vue教程中是有提到 Bus的用法 , 但是因为Vuex的存在 , 它被放在了一个很不起眼的地方 .

$dispatch$broadcast 已经被弃用。请使用更多简明清晰的组件间通信和更好的状态管理方案,如:Vuex
因为基于组件树结构的事件流方式实在是让人难以理解,并且在组件结构扩展的过程中会变得越来越脆弱。这种事件方式确实不太好,我们也不希望在以后让开发者们太痛苦。并且$dispatch$broadcast 也没有解决兄弟组件间的通信问题。
对于$dispatch$broadcast最简单的升级方式就是:通过使用事件中心,允许组件自由交流,无论组件处于组件树的哪一层。由于 Vue 实例实现了一个事件分发接口,你可以通过实例化一个空的 Vue 实例来实现这个目的。
这些方法的最常见用途之一是父子组件的相互通信。在这些情况下,你可以使用 v-on监听子组件上 e m i t 的 变 化 。 这 可 以 允 许 你 很 方 便 的 添 加 事 件 显 性 。 然 而 , 如 果 是 跨 多 层 父 子 组 件 通 信 的 话 , ‘ emit 的变化。这可以允许你很方便的添加事件显性。然而,如果是跨多层父子组件通信的话,` emit便emit` 并没有什么用。相反,用集中式的事件中间件可以做到简单的升级。这会让组件之间的通信非常顺利,即使是兄弟组件。因为 Vue 通过事件发射器接口执行实例,实际上你可以使用一个空的 Vue 实例。

为什么有Vuex , 但我仍然要推荐用它 看一下使用场景吧
比如这个按钮
TIM截图20191004195929.png
点击 展开后
TIM截图20191004200011.png
它可以通过点击叉叉关闭 , 这个很简单 , 但是我也实现点击别处自动关闭 可能是点击上栏 , 可能是滑动屏幕 或者其他你所想 .
很明显这是一件一件的事情 .
你可以设置Vuex 并在不同组件中的事件设置这个开关的状态buttonOpenState为 false
但是这个开关并非看到的一个状态那么简单 , 它涉及动画,防抖等 , 可能还需要执行某个开关函数完成这个功能 , 所以我们需要先computed返回这个Vuex中的值作为本地的状态(因为watch无法监测Vuex中的值) , 然后再设置watch来监控它的变化并执行开关函数 .
为了这个开关 , 我们要向Vuex存一个用完就丢的值 , 要专门copmputed返回一个值 , 还要写一个watch来执行函数 , 虽然比一层层传值好了很多但是比较冗杂 .
再比如一个被复用的通知框 , 一个状态是是否显示 , 一个状态是通知的内容 , 这时候Vuex就需要存两个变量 . 显得非常沉迂 .
这个时候事件Bus出场了
它的原理是使用 $emit, $on, $off 分别来分发、监听、取消监听事件
首先这个 Bus 的Vue实例是独立开项目中业务的
在某个页面新建文件 eventHub.js

import Vue from 'vue'
export default new Vue();

在这个页面引入这个Vue实例然后

//eventHub就是刚刚创建的bus实例
methods: {
  addTodo: function () {
    eventHub.$emit('add-todo', { text: this.newTodoText })
    this.newTodoText = ''
  }
}
created: function () {
  eventHub.$on('add-todo', this.addTodo)
  eventHub.$on('delete-todo', this.deleteTodo)
},
// 最好在组件销毁前
// 清除事件监听
beforeDestroy: function () {
  eventHub.$off('add-todo', this.addTodo)
  eventHub.$off('delete-todo', this.deleteTodo)
},

使用$emit 和 $on 发送 , 接受事件 . 这样子就完成了bus的功能
如果你不想每次都引入Bus实例你可以

//1.在main.js中挂载至原型链
Vue.prototype.bus = new Vue()
//2.写在Vuex里 与Vuex的模块对应
const schedule = {
    state:{
        week:0,
        Bus:new Vue(),
    },
    mutations:{
        changeWeek(state,par){
            state.week = par;
            
        }
    },
}
//3.使用依赖注入 , 一个页面把最上层的页面组件作为Bus , 
//比较推荐这种 , 写法简洁也保证一个页面一个Bus , 而且利用了Vue实例
//页面顶层组件
provide() {
	  return {
	    Bus: this,
	  }
	},
//页面内组件
inject:['Bus'],
	created() {
		this.Bus.$on('dosomething', function(){
            ...
        });
	},
	beforeDestroy() {
		this.Bus.$off('dosomething');
	},

实际上Bus是有缺点的 , 在vue-dev-tool 调试时 , 无法知道是哪个组件发出了事件 ($emit) 。所以虽然它非常简洁 , 但它只适合特定场景—别的组件想改变某个组件内部状态的情况 , 而组件间共享的数据 , 比如:一个日历组件中,选择星期数 , 有三四处子组件需要联动改变 , 这就应该用Vuex了
Bus -> 多组件改一组件
Vuex->多组件用一数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值