TS从入门到精通(十一)手写发布订阅模式

123 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

概述:

给大家说一下vuex与eventbus区别:vuex的场景是跨组件data通讯,EvnetBus是事件通讯,这两个完全就是不同的东西虽然功能看起来差不多,但是实现方式完全就是不一样的。之前子组件调用父组件的父组件需要两层$emit才能实现,兄弟组件之间通讯也是比较难以解决问题,这个时候我们就需要EventBus来帮助我们。

首先我们要先确定一下功能然后再做具体的代码实现。vue中事件总线的主要函数就是 on emit off once这四个。我们先明确一下具体功能

  1. emit 发布注册
  2. on 订阅监听
  3. off 解绑
  4. once 只执行一次 核心功能 on emit off ,once实现思路就是在调用过后立即删除 emit(name,args) name 自定义函数名 args 参数 on (name,cb) name 要监听的事件名称 cb 回调 once(name,cb) name 要监听的事件名称 cb 回调 off(name,cb) name 要卸载的事件 cb回调
  • 定义接口约束类
  • 定义数据格式
  • 在构造器初始化数据
  • on添加事件监听
  • emit触发事件
  • once在触发之后删除函数
  • off通过函数名删除事件监听
interface EventBus {
  on: (name: string, cb: Function) => void,
  emit: (name: string, ...args: Array<any>) => void,
  once: (name: string, cb: Function) => void,
  off?: (name: string, cb: Function) => void,
}
type List = {
  [key: string]: Array<Function>
}
class Bus implements EventBus {
  list: List
  constructor() {
    this.list = {}
  }
  on(name: string, cb: Function) {
    this.list[name] = this.list[name] || []
    this.list[name].push(cb);
  };
  emit(name: string, ...args: Array<any>) {
    let cbArr: Array<Function> = this.list[name]
    if (cbArr) {
      cbArr.forEach(fun => fun.call(this, args))
    }
  }
  once(name: string, cb: Function) {
    let temp = (...args: Array<any>) => {
      cb.apply(this, args)
      this.off(name, temp)
    }
    this.on(name, temp)
  }
  off(name: string, cb: Function) {
    let cbArr = this.list[name]
    if (cbArr && cb) {
      let index = cbArr.findIndex(fn => fn === cb)
      cbArr.splice(index, 1)
    }
  }
}
const o = new Bus();
o.on("buy", (data: Array<any>) => {
  console.log(data);
})
o.emit("buy", "001", "002")