自定义事件

379 阅读2分钟
function EventTarget () {
  this.handles = {}
}
EventTarget.prototype = {
  constructor: EventTarget,
  addHandler: function (type, handle) {
    if (typeof this.handles[type] === 'undefined') {
      this.handles[type] = []
    }
    this.handles[type].push(handle)
  },
  fire: function (event) {
    if (!event.target){
      event.target = this
    }
    if (this.handles[event.type] instanceof Array) {
      let handles = this.handles[event.type]
      for (let i = 0; i < handles.length; i++) {
        handles[i](event)
      }
    }
  },
  removeHandler: function (type, handle) {
    if (this.handles[type] instanceof Array) {
      let handles = this.handles[type]
      for (var i = 0; i < handles.length; i++) {
        if (handles[i] ===handle) {
          break
        }
      }
      handles.splice(i,1)
    }
  }
}
// EventTarget 类型有一个单独的属性 handlers,用于储存事件处理程序。
// 还有三个方法: addHandler(),用于注册给定类型事件的事件处理程序;
// fire(),用于触发一个事件;
// removeHandler(),用于注销某个事件类型的事件处理程序。
//
// addHandler()方法接受两个参数:事件类型和用于处理该事件的函数。
// 当调用该方法时,会进行 一次检查,看看 handlers 属性中是否已经存在一个针对该事件类型的数组;
// 如果没有,则创建一个新 的。然后使用 push()将该处理程序添加到数组的末尾
//
// 如果要触发一个事件,要调用 fire()函数。
// 该方法接受一个单独的参数,是一个至少包含 type 属性的对象。
// fire()方法先给 event 对象设置一个 target 属性,如果它尚未被指定的话。
// 然后它就 查找对应该事件类型的一组处理程序,调用各个函数,并给出 event 对象
// 。因为这些都是自定义事件, 所以 event 对象上还需要的额外信息由你自己决定。
//
// removeHandler()方法是 addHandler()的辅助,
// 它们接受的参数一样:事件的类型和事件处理 程序。
// 这个方法搜索事件处理程序的数组找到要删除的处理程序的位置。
// 如果找到了,则使用 break 操作符退出 for 循环。然后使用 splice()方法将该项目从数组中删除。

// 然后,使用 EventTarget 类型的自定义事件可以如下使用

function handleMessage (event) {
  alert('Message received:', event.message)
}
//创建一个新对象
var target = new EventTarget()
//添加一个事件处理程序 类似 vue里面的 eventBus.$on()
targrt.addHandler('message', handleMessage)
//触发事件 类似 vue里面的 eventBus.$emit
target.fire({ type: "message", message: "Hello world!"})
//删除事件处理程序
target.removeHandler('message', handleMessage)
//再次,应没有处理程序
target.fire({ type: "message", message: "Hello world!"});
// 因为这种功能是封装在一种自定义类型中的,其他对象可以继承 EventTarget 并获得这个行为,
function Person(name, age){ EventTarget.call(this); this.name = name; this.age = age;
}
inheritPrototype(Person,EventTarget);
Person.prototype.say = function(message){
  this.fire({type: "message", message: message});
};
// Person 类型使用了寄生组合继承(参见第 6 章)方法来继承 EventTarget。
// 一旦调用了 say() 方法,便触发了事件,它包含了消息的细节。
// 在某种类型的另外的方法中调用 fire()方法是很常见的, 同时它通常不是公开调用的。这段代码可以照如下方式使用:
function handleMessage(event){
  alert(event.target.name + " says: " + event.message);
}
//创建新 person
var person = new Person("Nicholas", 29);
//添加一个事件处理程序
person.addHandler("message", handleMessage);
//在该对象上调用 1 个方法,它触发消息事件
person.say("Hi there.");