昨天使用了 vue 提供的事件发布订阅, 于是今天就自己实现了一个, 发现没有太大难度, 直接上代码:
- function EventBus() {}
- EventBus.prototype.on = function (name, callback) {
- // 如果没有事件对象, 新增一个
- if(!this._events){
- // 创建一个干净的没有原型链的对象
- this._events = Object.create(null);
- }
- // 如果没有这个事件的订阅, 新增一个, 如果有, push 进去
- if(!this._events[name]){
- this._events[name] = [callback];
- }else{
- this._events[name].push(callback);
- }
- }
- EventBus.prototype.emit = function (name, ...args) {
- // 发布的时候, 如果有这个事件, 循环执行所有这个订阅的方法
- if(this._events[name]){
- this._events[name].forEach(callback => {
- callback(...args);
- })
- }
- }
- EventBus.prototype.off = function (name) {
- // 如果有这个事件的订阅, 清除所有订阅
- if(this._events[name]){
- delete this._events[name];
- }
- }
- EventBus.prototype.once = function (name, callback) {
- let once = (...args) => {
- callback(...args);
- this.off(name);
- };
- this.on(name, once);
- }
- let eventBus = new EventBus();
- eventBus.on('on', function (msg) {
- console.log(msg);
- })
- eventBus.once('once', function (msg) {
- console.log(msg);
- })
- eventBus.on('off', function (msg) {
- console.log(msg);
- })
- eventBus.emit('on', '发布 on1')// 发布 on1
- eventBus.emit('on', '发布 on2')// 发布 on2
- eventBus.emit('once', '发布 once')// 发布 once
- eventBus.emit('once', '发布 once')
- eventBus.emit('off', '发布 off')// 发布 off
- eventBus.off('off')
- eventBus.emit('off', '发布 off')
on,off 和 emit 没什么好说的, 就是很简单的发布订阅, 代码看一下也都理解了, once 这个方法我觉得得理解一下, once 方法其实就是执行 on, 执行一次之后执行 off, 我们可以采用函数劫持的方法, 把订阅的方法劫持了, 依然是执行 on, 但是回调变成自己的, 当自己的回调执行之后, off 移除这个订阅, 这种做法好像也叫切片编程.
- EventBus.prototype.once = function (name, callback) {
- let once = (...args) => {
- callback(...args);
- this.off(name);
- };
- this.on(name, once);
- }
昨天有人问我 eventBus 具体应用场景, 说实在的, 我还真想不出来, 兄弟组件之间传值, 多层级组件之间传值. 比如聊天点击进入一个页面, 未读消息这种, 大部分是在同一个页面展示, 然后不同一个组件的场景才用得到, 或者不同页面销毁一些会造成内存泄漏的场景. eventBus 能解决的都有其它方法可以解决, 其它方法也可以用 eventBus 解决, 或许以后用到了 eventBus 之后, 会觉得很香吧.
image
来源: http://www.jianshu.com/p/52f05569d7c8