返回列表

参照DOM3的EventListenerList机制对浏览器事件机制做了下扩展

默认分类 2017/03/26 07:08

一直觉得浏览器默认的事件管理机制不是很灵活,参照DOM3的EventListenerList机制简单做了一下扩展

<script>
/* global EventTarget*/
'use strict';

EventTarget.prototype.addEventListenerBase = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener) {
  if (!(listener instanceof Function)) {
    window.console.error('[listener] is not a function, from addEventListener(type, listener)');
    window.console.log(listener);
    return;
  }
  if (!this.EventList) this.EventList = {};
  if (!this.EventList[type]) this.EventList[type] = {index: 0};

  var result = -1;
  var list = this.EventList[type];
  for (var i = list.index - 1; i > -1; i--) {
    if (list[i] === listener) {
      result = i;
      break;
    }
  }
  if (result === -1) {
    result = list.index;
    list[list.index++] = listener;
  }

  this.addEventListenerBase.apply(this, arguments);

  return result;
};

EventTarget.prototype.removeEventListenerBase = EventTarget.prototype.removeEventListener;
EventTarget.prototype.removeEventListener = function(type, listener) {
  if (arguments.length === 0) {
    if (!this.EventList) this.EventList = {};
    for (var i in this.EventList) {
      if (this.EventList.hasOwnProperty(i)) {
        this.removeEventListener(i);
      }
    }
  } else if (arguments.length === 1) {
    if (this.EventList && this.EventList[type] && this.EventList[type].index) {
      for (var i = this.EventList[type].index - 1; i > -1; i--) {
        this.removeEventListener(type, i);
      }
    }
  } else if (arguments.length > 1) {
    if (!(listener instanceof Function) && !String(listener).replace(/\D/g, '')) {
      window.console.error('[listener] is not a function or number, from removeEventListener(type, listener)');
      window.console.log(listener);
      return;
    }
    if (!this.EventList) this.EventList = {};
    if (!this.EventList[type]) return;

    var list = this.EventList[type];
    for (var i = list.index - 1; i > -1; i--) {
      if (!list[i]) continue;
      if (listener === list[i] || String(listener) === String(i)) {
        this.removeEventListenerBase(type, list[i]);
        list[i] = undefined;
      }
    }
  }
};

function logg(str) {
  out.innerHTML += str + ' '
}

</script>
<button id="tt">click test</button> <br/><br/>
<button onclick="tt1.idx=tt.addEventListener('click', function() {logg('click 1');});">add1</button> 
<button onclick="tt2.idx=tt.addEventListener('click', function() {logg('click 2');});">add2</button> 
<button id="tt1" onclick="tt.removeEventListener('click', this.idx)">rm1</button> 
<button id="tt2" onclick="tt.removeEventListener('click', this.idx)">rm2</button> 
<button onclick="tt.removeEventListener('click')">rm_all</button> 
<button onclick="tt.removeEventListener()">clear_all</button> 
<br/>
<br/>
<div id="out"></div>