在循环中分配事件监听器的问题

Issue assigning event listeners in a loop - javascript

本文关键字:监听器 问题 事件 分配 循环      更新时间:2023-09-26

我做了一个自定义chrome扩展-书签管理器。它的工作很好,但我有删除链接的问题:如果3个链接给出,并删除按钮被点击在第二个,两个2和3将被删除。

html + js here: http://jsfiddle.net/6Txr9/

因为这是一个扩展,内联javascript是不可用的,它必须与事件监听器一起完成。

计数器和linkContainer保存在本地。这允许数据在文本启动之间持久化,并确保所有@id都是唯一的。这个想法是,indexDeleters()将在每次被调用时为每个按钮添加一个唯一的事件监听器,这将导致它只删除那一行。

任何输入都是赞赏的!

请求的代码(与上面的链接相同):

js

function addCats() 
{
    var linkCounter = localStorage['counter']
    var catsList = document.getElementById('catsList');
    var linkName = document.getElementById('linkName');
    var a = document.createElement('a');
    var linkContainer = document.getElementById('linkContainer');
    a.appendChild(document.createTextNode(document.getElementById('linkName').value));
    a.setAttribute('href', 'http://google.com/');
    a.setAttribute('target', '_blank');
    var deleteLink = document.createElement('img');
    deleteLink.setAttribute('src', 'red_x.png');
    deleteLink.setAttribute('align', 'right');
    deleteLink.setAttribute('id', linkCounter);
    var tr = document.createElement('tr');
    var linkCell = document.createElement('td');
    var xCell = document.createElement('td');
    linkCell.appendChild(a);
    xCell.appendChild(deleteLink);
    xCell.setAttribute('align', 'right');
    tr.appendChild(linkCell);
    tr.appendChild(xCell);
    linkContainer.appendChild(tr);
    catsList.value = '';
    linkName.value = '';
    localStorage['container'] = JSON.stringify(linkContainer.innerHTML);
    indexDeleters();
    linkCounter ++;
    localStorage['counter'] = linkCounter;
}
document.getElementById('addToList').onclick = addCats;
function indexDeleters()
{
    var Xs = document.getElementsByTagName('img');
    var arr = []
    for (var i=0; i<Xs.length; i++)
    {
        arr.push(Xs[i]);
    }
    for (var i=0; i<arr.length; i++)
    {
        var Id = arr[i].getAttribute('id');
        arr[i].addEventListener('click', function(){removeRow(Id);}, false);
    }
}
function removeRow(Id)
{
    console.log('Call to remove id at ' + Id)
    var Table = document.getElementById('linkContainer');
    var Tr = document.getElementById(Id).parentNode.parentNode
    Tr.parentNode.removeChild(Tr);
    localStorage['container'] = JSON.stringify(document.getElementById('linkContainer').innerHTML);
}
window.onload = function() 
{
    if (localStorage.getItem('counter') == null)
    {
        localStorage['counter'] = 0
    }
    document.getElementById('linkContainer').innerHTML = JSON.parse(localStorage['container']);
    indexDeleters();
}

<body>
<h2 align="center">Bookmark Manager</h2>
<table>
    <tr>
        <td colspan="5">
            <table id="linkContainer" width="100%"></table>
        </td>
    </tr>
    <tr>
        <td nowrap>Display Name:</td>
        <td>
            <input type="text" id="linkName"/>
        </td>
        <td nowrap>Cat IDs:</td>
        <td>
            <input type="text" id="catsList"/>
        </td>
        <td>
            <button type="button" id="addToList">Add</button>
        </td>
    </tr>
</table>
<script src="popup.js"></script>
</body>

请参见JavaScript closure inside loops -一个简单的实际例子来解释这个问题。

在您的例子中,您可以直接访问事件处理程序中的DOM元素,这样它就不依赖于任何循环变量。

arr[i].addEventListener('click', function(){removeRow(this.id);}, false);