实现观察者模式

我们希望实现的调用方式是这样的

option.on("click", arr => {
  let text = `名字:${arr.name} \n年龄:${arr.age} `
  console.log(text)
}) // 添加监听
option.emit("click", { name: "star", age: 23 }) // 触发监听事件
option.off("click") // 移除监听事件

所以下面我们会分为三步走

Step1 如何监听 on

function observer() {
  this.handles = {} // 定义一个容纳要监听事件的对像
}
observer.prototype.on = function(type, hander) {
  // 在原型上添加on方法
  // 为监听的事件添加到监听列表中
  if (!this.handles[type]) {
    this.handles[type] = []
  }
  // 将处理函数添加到事件对应的数组中
  this.handles[type].push(hander)
}

// 现在我们可以这样添加一个事件
const option = new observer()
option.on("click", arr => {
  // 这里是监听到click事件的回调
}) // 添加监听

Step2 如何触发事件 emit

observer.prototype.emit = function() {
  // 将参数转换为数组
  const arr = [].slice.call(arguments, 0)
  // 第一个参数为事件名称
  const type = arr[0]
  if (this.handles[type]) {
    // 如果已经添加监听函数,则触发回调
    this.handles[type].forEach(fun => {
      fun.apply(this, arr.slice(1))
    })
  } else {
    console.warn(`please add event "${type}" listener first`)
  }
}

Step3 如何取消监听的事件 off

observer.prototype.off = function(type) {
  if (this.handles[type]) {
    delete this.handles[type]
  }
}

我们可以向下面一样测试我们实现的观察者模式是否有效

const option = new observer()
option.on("click", arr => {
  let text = `名字:${arr.name} \n年龄:${arr.age} `
  console.log(text)
}) // 添加监听
option.emit("click", { name: "star", age: 23 }) // 触发监听事件
option.emit("hover") // 触发未监听事件
option.off("click") // 移除监听事件
option.emit("click") // 测试移除后的事件


打印结果如下
名字:star
年龄:23
please add event "hover" listener first
please add event "click" listener first
上次更新: 3/5/2020, 11:34:17 PM