Skip to content

发布订阅模式

什么是发布订阅模式,例如 addEventListenerVue evnetBus 都属于发布订阅模式

  • on订阅/监听

  • emit 发布/注册

  • once 只执行一次

  • off解除绑定

rollup 编译

与上一个案例相同

具体代码

ts
interface EventFace {
  on: (name: string, callback: Function) => void
  emit: (name: string, ...args: Array<any>) => void
  once: (name: string, fn: Function) => void
  off: (name: string, fn: Function) => void
}

interface Obj {
  [key: string]: Array<Function>
}

export class Dispatch implements EventFace {
  obj: Obj

  constructor() {
    this.obj = {}
  }
  
  on(name: string, callback: Function) {
    const callbackList = this.obj[name] || []
    callbackList.push(callback)
    this.obj[name] = callbackList
    console.log(this.obj)
  }

  emit(name: string, ...args: Array<any>) {
    let eventName = this.obj[name]
    if (eventName) {
      eventName.forEach(fn => {
        fn.apply(this, args)
      })
    } else {
      console.error(`输入的${name}名称错误`)
    }
  }

  once(name: string, fn: Function) {
    // 临时函数
    let de = (...args: Array<any>) => {
      fn.apply(this, args)
      this.off(name, de)
    }
    this.on(name, de)
  }

  off(name: string, fn: Function) {
    let eventName = this.obj[name]
    if (eventName && fn) {
      let index = eventName.findIndex(fns => fns === fn)
      eventName.splice(index, 1)
    } else {
      console.error(`输入的${name}名称错误`)
    }
  }

}

TIP

可以理解成 on 方法向中间存储对象的name属性的回调数组中,存一个新的回调函数,在外部调用的时候里面写接受参数的逻辑

emit 方法就是用来发送数据,通过 name 找到属于这个name属性的回调集合,集合中的回调函数使用apply方法,进行动态传参

apply

index.html

html
<!doctype html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>ts-rollup</title>

</head>
<script type="module">
  import {Dispatch} from '../lib/index.js'

  const o = new Dispatch()
  o.on('Gxx', (...args) => {
    console.log(args, 112312)
  })
  // const fn = (...args) => {
  //   console.log(args,23423)
  // }
  // o.on('Gxx', fn)
  // o.off('Gxx',fn)
  o.once('Gxx', (...args) => {
    console.log(args, 'once')
  })
  o.emit('Gxx', 1, false, {name: 'zx'})
  o.emit('Gxx', 2, false, {name: 'zx'})

</script>
<body>

</body>
</html>