addEventListener on NodeList

addEventListener on NodeList

本文关键字:NodeList on addEventListener      更新时间:2023-09-26

NodeList是否支持addEventListener。如果不是,将EventListener添加到NodeList的所有节点的最佳方式是什么。目前我正在使用如下所示的代码片段,有更好的方法吗。

var ar_coins = document.getElementsByClassName('coins');
for(var xx=0;xx < ar_coins.length;xx++)
{
        ar_coins.item(xx).addEventListener('dragstart',handleDragStart,false);
}

如果不循环遍历每个元素,就无法做到这一点。当然,你可以写一个函数来为你做这件事。

function addEventListenerList(list, event, fn) {
    for (var i = 0, len = list.length; i < len; i++) {
        list[i].addEventListener(event, fn, false);
    }
}
var ar_coins = document.getElementsByClassName('coins');
addEventListenerList(ar_coins, 'dragstart', handleDragStart); 

或者更专业的版本:

function addEventListenerByClass(className, event, fn) {
    var list = document.getElementsByClassName(className);
    for (var i = 0, len = list.length; i < len; i++) {
        list[i].addEventListener(event, fn, false);
    }
}
addEventListenerByClass('coins', 'dragstart', handleDragStart); 

而且,虽然你没有问过jQuery,但这正是jQuery特别擅长的东西:

$('.coins').on('dragstart', handleDragStart);

我能想到的最好的办法是:

const $coins = document.querySelectorAll('.coins')
$coins.forEach($coin => $coin.addEventListener('dragstart', handleDragStart));

请注意,这使用了ES6功能,所以请确保先将其转换!

实际上有一种方法可以在没有循环的情况下完成

[].forEach.call(nodeList,function(e){e.addEventListener('click',callback,false)})

这种方法被用于我的一个单行辅助库nanoQuery中。

最简单的例子是将此功能添加到NodeList

NodeList.prototype.addEventListener = function (event_name, callback, useCapture)
{
    for (var i = 0; i < this.length; i++)
    {
      this[i].addEventListener(event_name, callback, useCapture);
    }
};

现在你可以做:

document.querySelectorAll(".my-button").addEventListener("click", function ()
{
    alert("Hi");
});

用同样的方法,你可以做一个forEach循环

NodeList.prototype.forEach = function (callback)
{
    for (var i = 0; i < this.length; i++)
    {
      callback(this[i], i);
    }
};

使用:

document.querySelectorAll(".buttons").forEach(function (element, id)
{
    input.addEventListener("change", function ()
    {
        alert("button: " + id);
    });
});

EDIT:请注意,NodeList.prototype.forEach自2016年11月以来一直存在于FF中。尽管

,但不支持IE

在es6中,您可以使用array.from从nodelist中创建数组,例如

ar_coins = document.getElementsByClassName('coins');
Array
 .from(ar_coins)
 .forEach(addEvent)
function addEvent(element) {
  element.addEventListener('click', callback)
}

或者只使用箭头功能

Array
  .from(ar_coins)
  .forEach(element => element.addEventListener('click', callback))

另一个解决方案是使用事件委派。您只需将addEventListener用于.coins元素的最近父元素,并在回调中使用event.target来检查单击是否真的在类为"coins"的元素上。

我想另一个选项是使用Object.definePropertyNodeList上定义addEventListener。这样,您就可以像对待单个节点一样对待NodeList。

例如,我在这里创建了一个jsfiddle:http://jsfiddle.net/2LQbe/

关键是:

Object.defineProperty(NodeList.prototype, "addEventListener", {
    value: function (event, callback, useCapture) {
        useCapture = ( !! useCapture) | false;
        for (var i = 0; i < this.length; ++i) {
            if (this[i] instanceof Node) {
                this[i].addEventListener(event, callback, useCapture);
            }
        }
        return this;
    }
});

您也可以使用原型

NodeList.prototype.addEventListener = function (type, callback) {
    this.forEach(function (node) {
        node.addEventListener(type, callback);
    });
};