ts:简单实现发布订阅模式

小满老师课程观看的随笔~

前言:什么是发布订阅模式?

  • 比如 原生js 中的 addEventListenerremoveEventListener
  • 比如 vue 中的 EventBus(全局事件总线)($emit、$on)
  • 收集 一些事件后,统一处理
  • 发布者 $emit,订阅者 $on,再加一个调度者(调度中心)

实战编写

  • type/index.js 存放 类型约束
// 存放事件的容器约束,key是事件名,value是对应的事件列表
export interface List {
  [key: string]: Array<Function>
}

// 类的约束
export interface DispatchClass {
  on: (name: string, fn: Function) => void
  emit: (name: string, ...args: Array<any>) => void
  off: (name: string, fn: Function) => void
  once: (name: string, fn: Function) => void
}
  • index.ts 存放主要逻辑
import { DispatchClass, List } from './type/index'

// 调度中心
class Dispatch implements DispatchClass {
  // 存放事件的容器
  list: List

  constructor () {
    this.list = {}
  }

  // 注册事件
  on (name: string, fn: Function) {
    // 把传入的事件放入对应名称的事件数组中
    let callbacks = this.list[name] || []
    callbacks.push(fn)
    this.list[name] = callbacks
  }

  // 调用事件
  emit (name: string, ...args: Array<any>) {
    const callbacks = this.list[name]
    if (callbacks && callbacks.length) {
      // 找到名称对应的事件数组,将数组中事件全部调用
      callbacks.forEach(fns => {
        fns.apply(this, args)
      })
    } else {
      console.log('无可调用的事件,名称错误')
    }
  }

  // 解绑事件
  off (name: string, fn: Function) {
    // 找到对应名称下的事件数组,删除指定的事件函数
    const callbacks = this.list[name]
    if (callbacks && fn) {
      const index = callbacks.findIndex(fns => fns === fn)
      if (index > -1) {
        callbacks.splice(index, 1)
      }
    } else {
      console.log('该事件未监听')
    }
  }

  // 注册一个仅执行一次的事件:执行结束后立刻解绑(仅注册,还是需要 emit 执行)
  once (name: string, fn: Function) {
    // 创建一个临时函数用于绑定,在临时函数内部执行完 fn 之后即刻解绑
    const temFn = (...args: Array<any>) => {
      fn.apply(this, args)
      this.off(name, temFn)
    }
    this.on(name, temFn)
  }
}


// 使用:
const o = new Dispatch()

const callback1 = (...args: any) => {
  console.log('1111--callback', args)
}
const callback2 = (...args: any) => {
  console.log('2222--callback', args)
}
const callback3 = (...args: any) => {
  console.log('3333--callback', args)
}

// 注册了两个回调函数 给 test
o.on('test', callback1)
o.on('test', callback2)

// 这里调用后,就会执行两个函数
o.emit('test', 123, false, { name: 'blue' })

// 这里先解绑一个事件
o.off('test', callback1)
// 这里再调用就只会执行一个了(callback2)
o.emit('test', 456, true, { name: 'blue' })


// 注册一个仅执行一次的事件
o.once('test2', callback3)
// 调用这个事件
o.emit('test2', 789, false)
// 第二次调用,找不到了,无法调用
o.emit('test2','once第二次调用')

你可能感兴趣的:(Typescript,typescript,发布订阅模式,前端)