Open liangbus opened 4 years ago
这个问题还经常在网上看到,碰巧之前有看过一个类似的库的源码,就复习一下,写了个简单的能用的消息订阅组件
其实原理很简单,就是通过一个对象去把订阅的事件去存起来,然后触发的时候,把订阅过的事件都执行一遍就好了,需要注意的是,订阅源可能会有多个,因此需通过一个自加变更去避免覆盖,这也利用了闭包的特性。
以下是可以直接使用的代码
(function(root, factory){ root.onfire = factory() })(window, function(){ var __eventList = {} var __counter = 0 function on(eventName, callback, context = window) { return __bind(eventName, callback, context) } function __bind(eventName, callback, context = window, isOnce = false) { if(!__eventList[eventName]) { __eventList[eventName] = {} } __eventList[eventName][++__counter] = [callback, context, isOnce] return [eventName, __counter] } function fire(eventName) { var args = [].slice.call(arguments, 1) __invokeFunc(eventName, ...args) } function __invokeFunc(eventName) { var __triggerEvent = __eventList[eventName] if(!__triggerEvent) return var args = [].slice.call(arguments, 1) // 遍历列表 for(let key in __triggerEvent) { var eventTarget = __triggerEvent[key] if (eventTarget) { eventTarget[0].apply(eventTarget[1], args) // if is invoked onced, when it done, reset it if(eventTarget[2]) { __triggerEvent[key] = null } } } } function remove(eventTarget) { var __triggerEvent = __eventList[eventTarget[0]] __triggerEvent[eventTarget[1]] = null } function once(eventName, callback, context) { return __bind(eventName, callback, context, true) } return { on, fire, once, remove } })
观察者模式在实际中常见的应用有 DOM 事件的监听
其实观察者模式跟发布订阅模式很相似,都是一对多的依赖关系
而主要的区别就是,发布订阅模式,会有一个存储事件的消息中心,也就是上面 __eventList 对象,发布者不需要知会订阅者存不存在,只需要关心自己发布的消息即可
观察者模式则需要提前声明好观察者对象,并加入监听的队列中,当发布者发布消息之后,触发观察者相应的方法
相比起来,发布订阅更加灵活,耦合性更低,所以在实际开发中用得更加广泛
下面是简单的观察者模式实现
class Subject { constructor() { this.subsQueue = [] } add(obs) { this.subsQueue .push(obs) } notify(data) { this.subsQueue .forEach(subTarget => { subTarget .update(data) }) } } class Observer { update(data) { console.log('updated: ', data) } }
能否手写一个发布/订阅模式?
这个问题还经常在网上看到,碰巧之前有看过一个类似的库的源码,就复习一下,写了个简单的能用的消息订阅组件
其实原理很简单,就是通过一个对象去把订阅的事件去存起来,然后触发的时候,把订阅过的事件都执行一遍就好了,需要注意的是,订阅源可能会有多个,因此需通过一个自加变更去避免覆盖,这也利用了闭包的特性。
以下是可以直接使用的代码
与观察者模式异同
观察者模式在实际中常见的应用有 DOM 事件的监听
其实观察者模式跟发布订阅模式很相似,都是一对多的依赖关系
而主要的区别就是,发布订阅模式,会有一个存储事件的消息中心,也就是上面 __eventList 对象,发布者不需要知会订阅者存不存在,只需要关心自己发布的消息即可
观察者模式则需要提前声明好观察者对象,并加入监听的队列中,当发布者发布消息之后,触发观察者相应的方法
相比起来,发布订阅更加灵活,耦合性更低,所以在实际开发中用得更加广泛
下面是简单的观察者模式实现