该模式,广泛地运用于异步实现中。

一、普通的发布、订阅实例

参与者

  • 发布者:事件的触发方
  • 订阅者:一群用户,等待接收信息

    流程

  • 1、发布者获取用户列表(添加订阅者)

  • 2、发布者触发信息(群发给订阅者) ``` class Man { constructor(key, name) { this.key = key this.name = name }

    getMsg(data) { console.log(this.name + ‘get data:’ + data) } }

class Sub { constructor() { this.clientList = [] }

add(user) { let idArr = this.clientList.map(item => item.key) if (!idArr.includes(user.key)) { this.clientList.push(user) } }

notify(data) { this.clientList.forEach(item => { item.getMsg(data) }) } }

let s = new Sub() let m1 = new Man(1, ‘chp’) let m2 = new Man(2, ‘cc’) s.add(m1) s.add(m2)

s.notify(‘股票涨了’)

  1. <a name="BJe9j"></a>
  2. ### 二、有中间人的发布、订阅模式
  3. > 模拟 window.addEventListener
  4. <a name="bWo5N"></a>
  5. #### 参与者
  6. - 发布者
  7. - 订阅者
  8. - 中间人
  9. <a name="yAbA9"></a>
  10. #### 流程
  11. 看到知乎上一条评论说的好:
  12. - 以前送快递:
  13. > 快递员 -> 用户
  14. - 现在送快递:
  15. > 快递员 -> 菜鸟驿站 -> 用户

class Event { constructor() { this.fnObj = {} }

listen(key, fn) { if (!this.fnObj[key]) { this.fnObj[key] = [] } this.fnObj[key].push(fn) }

trigger(…args) { let key = args[0] let otherArgs = args.slice(1) if (!this.fnObj[key]) { return }

  1. for (let i = 0, fn; fn = this.fnObj[key][i++];) {
  2. fn.apply(this, otherArgs)
  3. }

} }

let event = new Event()

event.listen(‘Dota’, (data) => { console.log(‘正在为您点播Dota内容:’, data) }) // addEventListener是可以添加多个事件的 event.listen(‘Dota’, (data) => { console.log(‘同时还会为您做其他事情’, data) })

event.listen(‘LOL’, (data) => { console.log(‘点播一些LOL的内容’, data) })

event.trigger(‘Dota’, ‘波波卡打野被抓’) ```

三、与Vue

如果我们再仔细想想,Vue的实现,所谓的“数据驱动”,应该也是与发布、订阅模式相关的。

数据改变 -> dom变化,就像有人去通知了一样。