web-dev-qa-db-ja.com

NodeListのaddEventListener

NodeListはaddEventListenerをサポートしていますか?そうでない場合は、NodeListのすべてのノードにEventListenerを追加する最良の方法は何ですか。現在私は以下に示すようにコードスニペットを使用していますが、これを行うためのより良い方法があります。

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

すべての要素をループせずにそれを行う方法はありません。もちろん、それを行う関数を書くこともできます。

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

私が思いつくことができた最高のものはこれでした:

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

これはES6の機能を使用しているため、まずトランスパイルするようにしてください。

13
Kris Selbekk

実際にはisこれを行う方法ループなしがあります:

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

そして、この方法は私のワンライナーヘルパーライブラリの1つで使用されています nanoQuery

9
Multiversum

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

最も簡単な例は、この機能を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サポートは

5
Profesor08

別のオプションは、Object.definePropertyを使用してaddEventListenerNodeListを定義することだと思います。これにより、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;
    }
});
1
Duncan

別の解決策は、イベント委任を使用することです。 「.coins」のクローゼットの親にeventlistenerを追加し、コールバックでevent.targetを使用して、「coins」クラスの要素がクリックされたかどうかを確認します。

1
user414873

プロトタイピングを使用することもできます

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