发布-订阅
在发布/订阅模式中,订阅者和发布者并不需要关心对方的状态,订阅者只管订阅事件并注册回调、发布者只管发布事件,其余一切交给调度中心来调度,从而能实现解耦。
首先要实现一个 Event 类,它应该含有一个收集回调函数的对象,和提供三个基础方法:on(订阅)、 emit(发布)、 off(注销)。
// event.js class Event { /** * on 方法把订阅者所想要订阅的事件及相应的回调函数记录在 Event 对象的 _cbs 属性中 */ on (event, fn) { if (typeof fn != "function") { console.error('fn must be a function') return } this._cbs = this._cbs || {} ;(this._cbs[event] = this._cbs[event] || []).push(fn) } /** * emit 方法接受一个事件名称参数,在 Event 对象的 _cbs 属性中取出对应的数组,并逐个执行里面的回调函数 */ emit (event) { this._cbs = this._cbs || {} var callbacks = this._cbs[event], args if (callbacks) { callbacks = callbacks.slice(0) args = [].slice.call(arguments, 1) for (var i = 0, len = callbacks.length; i < len; i++) { callbacks[i].apply(null, args) } } } /** * off 方法接受事件名称和当初注册的回调函数作参数,在 Event 对象的 _cbs 属性中删除对应的回调函数。 */ off (event, fn) { this._cbs = this._cbs || {} // all if (!arguments.length) { this._cbs = {} return } var callbacks = this._cbs[event] if (!callbacks) return // remove all handlers if (arguments.length === 1) { delete this._cbs[event] return } // remove specific handler var cb for (var i = 0, len = callbacks.length; i < len; i++) { cb = callbacks[i] if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1) break } } return } }
使用方法:
订阅 “publishHandle” 事件
import event from './event.js' event.on('publish',this.publishHandle.bind(this)) publishHandle: function(value) { ... }, ...
发布 “publishHandle” 事件
import event from './event.js' function() { ... event.emit('publish', value) },
注销事件
import event from './event.js' function(){ // remove all event.off() // remove all callbacks event.off('publish') // remove specific callbacks event.off('publish', this.publishHandle) }