利用Javascript实现一套自定义事件机制(3)

上面实现中给事件处理函数的实参中必定包含以下信息:

  • type : 当前触发的事件类型
  • origin : 当前事件绑定到的对象
  • scope : 事件处理函数的执行上下文

此外不同事件在各种的触发时可为此事件对象中加入各自不同的信息。

关于 Object.assign(target, ...sources) 是ES6中的一个方法,作用是将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象,类似于大家熟知的$.extend(target,..sources) 方法。

事件取消

事件取消中需要做的就是已经绑定的事件处理函数移除掉即可。

实现如下:

{
 /**
  * 取消绑定一个事件
  * 
  * @param {String} type 取消绑定的事件名称
  * @param {Function} fn 要取消绑定的事件处理函数,不指定则移除当前事件类型下的全部处理函数
  * @returns 当前实例对象
  */
 off: function (type, fn) {
  type = type.toLowerCase();
  var eventArr = this._events[type];
  if (!eventArr || !eventArr.length) return this;
  if (!fn) {
   this._events[type] = eventArr = [];
  } else {
   for (var i = 0; i < eventArr.length; ++i) {
    if (fn === eventArr[i][0]) {
     eventArr.splice(i, 1);
     // 1、找到后不能立即 break 可能存在一个事件一个函数绑定多次的情况
     // 删除后数组改变,下一个仍然需要遍历处理!
     --i;
    }
   }
  }
  return this;
 }
}

此处实现类似原生的事件取消绑定,如果指定了事件处理函数则移除指定事件的指定处理函数,如果省略事件处理函数则移除当前事件类型下的所有事件处理函数。

仅触发一次的事件

jQuery中有一个 one 方法,它所绑定的事件仅会执行一次,此方法在一些特定情况下非常有用,不需要用户手动取消绑定这个事件。

这里的实现也非常简单,只用在触发这个事件时取消绑定即可。

实现如下:

{
 /**
  * 绑定一个只执行一次的事件
  * 
  * @param {String} type 事件类型
  * @param {Function} fn 事件处理函数
  * @param {Object} scope 要为事件处理函数绑定的执行上下文
  * @returns 当前实例对象
  */
 one: function (type, fn, scope) {
  var that = this;
  function nfn() {
   // 执行时 先取消绑定
   that.off(type, nfn);
   // 再执行函数
   fn.apply(scope || that, arguments);
  }
  this.on(type, nfn, scope);
  return this;
 }
}

原理则是不把用户指定的函数直接绑定上去,而是生成一个新的函数,并绑定,此函数执行时会先取消绑定,再执行用户指定的处理函数。

基本雏形