事件侦听器包装函数-事件侦听器为元素绑定多个

时间:2019-05-01 01:21:23

标签: javascript html

下面是元素的事件侦听器的包装函数,如何处理事件侦听器包装函数中可以为一个元素绑定多次的事件侦听器。如果事件监听器绑定不止一次,那是什么意思,我只是在另一篇文章中听到过

var evts = (function () {
  'use strict';

  var listeners = [],
      add,
      remove;

  add = function (evt, elem, fn, capture) {
    var callback = function (evt) {      
      fn.call(elem, evt, evt && evt.target ? evt.target : window.event.srcElement);
    };

    listeners.push({
      evt: evt,
      elem: elem,
      fn: fn,
      callback: callback,
      capture, capture,
      removed: false
    });

    if (elem.addEventListener) {
      elem.addEventListener(evt, callback, capture);
    } else if (elem.attachEvent) {
      elem.attachEvent('on' + evt, callback, capture);
    } else {
      elem['on' + evt] = callback;
    }
  };

  remove = function (evt, elem, fn, capture) {

    var callback = function (evt) {      
      fn.call(elem, evt, evt && evt.target ? evt.target : window.event.srcElement);
    };

    callback();

    listeners.forEach(function (obj, i) {
      if (obj.evt === evt && obj.elem === elem && 
          !obj.removed) {
        obj.removed = true;
        callback = obj.callback;
        listeners.splice(i, 1);
      }
    });

    if (elem.removeEventListener) {
      elem.removeEventListener(evt, callback, capture);
    } else if (elem.detachEvent) {
      elem.detachEvent('on' + evt, callback, capture);
    } else {
      elem['on' + evt] = null;
    }
  };

  return {
    add: add,
    remove: remove
  };
}());

例如removeEvent Listener

$(this).off('click', function(e) { console.log('goodbye') });

1 个答案:

答案 0 :(得分:1)

看来OP代码是没有原型的ES5类?以下演示是称为class的ES6 Binder() -在此article中找到的修改版本:

  • constructor接受选择器(具有CSS / jQuery语法的字符串),并返回嵌套在对象{中的NodeList, NodeList } < / p>

  • 第一个方法.each(callback)将在每个节点(元素,标签等)上调用给定的回调(触发事件时调用的函数)。

  • 下一个方法.on(event, callback)将使用.each()方法绑定给定事件并向每个节点注册给定回调。

  • 最后一个方法.off(event, callback)删除具有给定事件和回调的eventListener()

Binder()使用以下语法实例化:

const $ = selector => new Binder(selector)

以下是将输入事件绑定到所有<input>s并调用function validate()的方法:

$('input').on('input', validate)

class Binder {
  constructor(selector) {
    const elements = document.querySelectorAll(selector);
    this.length = elements.length;
    Object.assign(this, elements);
  }
  each(callback) {
    for (let node of Array.from(this)) {
      callback.call(node);
    }
    return this;
  }
  on(event, callback) {
    return this.each(function() {
      this.addEventListener(event, callback);
    });
  }
  off(event, callback) {
    return this.each(function() {
      this.removeEventListener(event, callback);
    });
  }
};

const $ = selector => new Binder(selector);

const colorBtn = e => {
  const tgt = e.target;
  if (tgt.matches('button')) {
    if (tgt.matches('.off')) {
      tgt.style.color = tgt.id;
    } else {
      tgt.style.color = '#000';
    }
    tgt.classList.toggle('off');
  }
  return false;
}

const unbindBtn = e => {
  const tgt = e.target;
  if (tgt.checked) {
    $('button').off('click', colorBtn);
  } else {
    $('button').on('click', colorBtn);
  }
  return false;
}

$('button').on('click', colorBtn);
$('#unbind').on('change', unbindBtn);
button {
  display: block;
  width: 8ch;
  font-variant: small-caps;
  cursor: pointer
}

button::before {
  content: attr(id);
}

.highlight {
  background: yellow;
}
<button id="red" class='off'></button>
<button id="green" class='off'></button>
<button id="blue" class='off'></button>
<label for='unbind'>Remove Event Listeners<input id='unbind' type='checkbox'>