Javascript 在 NodeList 上添加事件监听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12362256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:49:21  来源:igfitidea点击:

addEventListener on NodeList

javascriptaddeventlistenernodelist

提问by Dinesh P.R.

Does NodeList support addEventListener. If not what is the best way to add EventListener to all the nodes of the NodeList. Currently I am using the code snippet as show below, is there a better way to do this.

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);
}

回答by jfriend00

There is no way to do it without looping through every element. You could, of course, write a function to do it for you.

如果不循环遍历每个元素,就没有办法做到这一点。当然,您可以编写一个函数来为您执行此操作。

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); 

or a more specialized version:

或更专业的版本:

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); 

And, though you didn't ask about jQuery, this is the kind of stuff that jQuery is particularly good at:

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

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

回答by Kris Selbekk

The best I could come up with was this:

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

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

Note that this uses ES6 features, so please make sure to transpile it first!

请注意,这使用了 ES6 功能,因此请确保先将其转译!

回答by Multiversum

There actually isa way to do this withouta loop:

实际上一种方法可以在没有循环的情况下做到这一点:

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

And this way is used in one of my one-liner helper libraries - nanoQuery.

这种方式用于我的单行助手库之一 - nanoQuery

回答by Profesor08

The simplest example is to add this functionality to NodeList

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

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

Now you can do:

现在你可以这样做:

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

In the same way, you can do a forEachloop

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

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

Using:

使用:

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

EDIT: note that NodeList.prototype.forEach has existed ever since november 2016 in FF. No IE support though

编辑:请注意 NodeList.prototype.forEach 自 2016 年 11 月以来在 FF 中一直存在。虽然没有 IE 支持

回答by Darlan Mendon?a

in es6, you can do a array from nodelist, using Array.from, e.g.

在 es6 中,您可以使用 Array.from 从节点列表中创建一个数组,例如

ar_coins = document.getElementsByClassName('coins');
Array
 .from(ar_coins)
 .forEach(addEvent)

function addEvent(element) {
  element.addEventListener('click', callback)
}

or just use arrow functions

或者只使用箭头函数

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

回答by Duncan

I suppose another option would be to define addEventListeneron NodeListusing Object.defineProperty. That way you can treat the NodeList as you would a single Node.

我想,另一种选择是定义addEventListenerNodeList使用Object.defineProperty。这样你就可以像对待单个节点一样对待 NodeList。

As an example, I created a jsfiddle here: http://jsfiddle.net/2LQbe/

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

The key point is this:

关键是这样的:

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;
    }
});

回答by user414873

Another solution is to use event-delegation. You just add an eventlistener to the closets parent of the ".coins" and use event.target in the callback to check if the click was really on an element with the class "coins".

另一种解决方案是使用事件委托。您只需将事件侦听器添加到“.coins”的壁橱父项,并在回调中使用 event.target 来检查单击是否真的位于具有“coins”类的元素上。

回答by Jon Allen

You could also use prototyping

你也可以使用原型

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