以下是手写系列内容预告,初步计划一周一个主题。
......(根据小伙伴的提议待定)
Subject是构造函数,new Subject() 创建一个主题对象,该对象内部维护订阅当前主题的观察者数组。主题对象上有一些方法,如添加观察者(addObserver)、删除观察者(removeObserver)、通知观察者更新(notify)。 当notify 时实际上调用全部观察者 observer 自身的 update 方法。
Observer 是构造函数,new Observer() 创建一个观察者对象,该对象有一个 update 方法,观察者可以订阅主题,实际上是把自己加入到主题的订阅者列表里。
class Subject { observers = [] addObserver(observer) { this.observers.push(observer) } removeObserver(observer) { let index = this.observers.indexOf(observer) if(index > -1){ this.observers.splice(index, 1) } } notify() { this.observers.forEach(observer => { observer.update() }) } } class Observer{ update() {} subscribeTo(subject) { subject.addObserver(this) } }
测试代码
let subject = new Subject() let observer = new Observer() observer.update = function() { console.log('observer update') } observer.subscribeTo(subject) //观察者订阅主题 subject.notify()
观察者模式和发布订阅模式具体的写法和区别没有官方的定义,下面这种写法反而更常见。
class EventBus { map = {} on(type, handler) { this.map[type] = (this.map[type] || []).concat(handler) } fire(type, data) { this.map[type] && this.map[type].forEach(handler => handler(data)) } off(type, handler) { if(this.map[type]) { if(!handler) { delete this.map[type] } else { let index = this.map[type].indexOf(handler) this.map[type].splice(index, 1) } } } }
测试代码
const eventBus = new EventBus() eventBus.on('click:btn', data => { console.log(data) }) eventBus.fire('click:btn', {a: 1, b: 2}) eventBus.off('click:btn') eventBus.fire('click:btn', {a: 1, b: 2})
如果觉得有用,点个赞让作者开心一下呗~
饥人谷一直致力于培养有灵魂的编程者,打造专业有爱的国内前端技术圈子。如造梦师一般帮助近千名不甘寂寞的追梦人把编程梦变为现实,他们以饥人谷为起点,足迹遍布包括facebook、阿里巴巴、百度、网易、京东、今日头条、大众美团、饿了么、ofo在内的国内外大小企业。 了解培训课程:加微信 xiedaimala03,官网:https://jirengu.com