1

自動的に onclick イベントが割り当てられたボタン リストを作成しようとしています。

document.getElementById('buttonList').innerHTML = '';
for(var $c = 0; $c < $buttons.length; $c++) {
    document.getElementById('buttonList').innerHTML += '<li><button id="button-' + $c + '">' + $buttons[$c].text + '</button></li>';
    document.querySelector('#button-' + $c).onclick = (function($index) {
        return function() {
            console.log($index);
        };
    })($c);
}

私の意見では、ボタンをクリックすると 0/1/2/3/ がログに記録されるはずですが、最後のボタンを除いて、どのボタンも機能していません。最後のボタンは正しいインデックスを返します。

だから私の質問、何が悪いのですか?

4

2 に答える 2

2

プロパティを変更するinnerHTMLと、要素が再レンダリングされるため、バインドした要素onclickは DOM に存在しなくなります (最後の要素を除く)。

MDNから:

要素の子をすべて削除し、コンテンツ文字列を解析して、結果のノードを要素の子として割り当てます。

それでも を使用したい場合innerHTMLの解決策は、コンテナー要素 ( <li>) を作成し、それをリストに追加してから、その を変更することinnerHTMLです。

document.getElementById('buttonList').innerHTML = '';
for (var $c = 0; $c < $buttons.length; $c++) {
    var liItem = document.createElement("li");
    document.getElementById('buttonList').appendChild(liItem);
    liItem.innerHTML = '<button id="button-' + $c + '">' + $buttons[$c].text + '</button>';
    console.log(document.querySelector('#button-' + $c));
    document.querySelector('#button-' + $c).onclick = (function ($index) {
        return function () {
            console.log($index);
        };
    })($c);
}

フィドルの例

于 2013-11-12T18:43:56.720 に答える
2

を使用innerHTML += ...すると、古いonclickハンドラが破棄されます。これは、次の 2 つの方法のいずれかで修正できます。

  • appendChildの代わりに使用innerHTML += ...:

    document.getElementById('buttonList').innerHTML = '';
    for(var $c = 0; $c < $buttons.length; $c++) {
        var li = document.createElement('li');
        var button = document.createElement('button');
        button.setAttribute('id', 'button-' + $c);
        button.innerHTML = $buttons[$c].text;
        button.onclick = (function($index) {
            return function() {
                console.log($index);
            };
        })($c);
        li.appendChild(button);
        document.getElementById('buttonList').appendChild(li);
    }
    
  • 最初に HTML を生成してから、イベント ハンドラーを一度に追加します。

    document.getElementById('buttonList').innerHTML = '';
    for(var $c = 0; $c < $buttons.length; $c++) {
        document.getElementById('buttonList').innerHTML += '<li><button id="button-' + $c + '">' + $buttons[$c].text + '</button></li>';
    }
    
    for(var $c = 0; $c < $buttons.length; $c++) {
        document.querySelector('#button-' + $c).onclick = (function($index) {
            return function() {
                console.log($index);
            };
        })($c);
    }
    
于 2013-11-12T18:44:26.823 に答える