在循环中添加'click'事件侦听器

在循环中添加'click'事件侦听器

onClickhtml标签中的标准重构为监听器,遇到了我的代码问题:

var td;
    for (var t=1;t<8;t++){
        td = document.getElementById('td'+t);
        if (typeof window.addEventListener==='function'){
                td.addEventListener('click',function(){
                    console.log(td);
            })}
 }

td单击元素时,假设td用循环中的最后一个索引单击,例如7
看起来像是eventListeners仅填充了此循环中的最后一个元素。
循环初始化看起来正确 
为什么会这样?

这是实时代码


汪汪一只猫
浏览 389回答 3
3回答

小唯快跑啊

您需要将事件侦听器的赋值包装在闭包中,例如:var&nbsp;td;for&nbsp;(var&nbsp;t&nbsp;=&nbsp;1;&nbsp;t&nbsp;<&nbsp;8;&nbsp;t++){ &nbsp;&nbsp;&nbsp;&nbsp;td&nbsp;=&nbsp;document.getElementById('td'+t); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(typeof&nbsp;window.addEventListener&nbsp;===&nbsp;'function'){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(function&nbsp;(_td)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;td.addEventListener('click',&nbsp;function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(_td); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})(td); &nbsp;&nbsp;&nbsp;&nbsp;}}

梦里花落0921

发生了什么变量td是在事件处理程序之外定义的,因此当您单击单元格时,您将记录它设置的最后一个值。更技术上:每个事件处理函数都是一个闭包 - 一个引用外部作用域变量的函数。一般的解决方案这类问题的一般解决方案是从包装函数返回事件处理程序,将要“修复”的变量作为参数传递:td.addEventListener('click',&nbsp;function(wrapTD)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;function()&nbsp;{&nbsp;console.log(wrapTD);&nbsp;}}(td));参数现在绑定到调用的包装函数的范围。更简单的解决方案:使用&nbsp;this然而,有一个更简单的选择。在事件处理程序中,this设置为定义处理程序的元素,因此您可以使用this而不是td:td.addEventListener('click',&nbsp;function()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;console.log(this);});更简单:没有循环!最后,您可以for完全摆脱循环并在整个表上设置单个事件处理程序:var&nbsp;table&nbsp;=&nbsp;document.getElementById('my-table');table.addEventListener('click',&nbsp;function(e)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e.target.nodeName.toUpperCase()&nbsp;!==&nbsp;"TD")&nbsp;return; &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;td&nbsp;=&nbsp;e.target; &nbsp;&nbsp;&nbsp;&nbsp;console.log(td);});对于较大的表,这是一个更好的解决方案,因为您只用一个替换多个事件处理程序。请注意,如果将文本包装在另一个元素中,则需要对其进行调整以检查目标元素是否为a的后代td。

万千封印

所以这里发生的是你将变量'td'保留在事件监听器函数的范围内。只有1个'td'实例,每次for循环迭代时都会更新。因此,当for循环结束时,td的值现在设置为元素'#td7',并且您的事件处理程序只是记录td的当前值。在上面的示例中,您只需记录'this':var&nbsp;td;for&nbsp;(var&nbsp;t=1;t<8;t++){ &nbsp;&nbsp;&nbsp;&nbsp;td&nbsp;=&nbsp;document.getElementById('td'+t); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(typeof&nbsp;window.addEventListener==='function'){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;td.addEventListener('click',function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(this); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;}}因为'this'被设置为一个事件被绑定的元素,用于执行事件处理程序。我猜你在寻找关于在for循环中创建闭包时保持迭代器的更多答案。为此,您需要在for循环之外定义一个函数。for&nbsp;(var&nbsp;t=1;t<8;t++){ &nbsp;&nbsp;bind_event(t);}function&nbsp;bind_event(t)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;td&nbsp;=&nbsp;document.getElementById('td'+t); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(typeof&nbsp;window.addEventListener==='function'){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;td.addEventListener('click',function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(td); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;}}这样,每次运行bind_event时都会创建一个名为'td'的变量实例,并且该实例将保留在事件监听器函数的闭包中。值得注意的是bind_event中的't'也是一个新变量。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript