JavaScript 事件在 for 循环中被覆盖

JavaScript event being overwritten in for loop

本文关键字:覆盖 循环 for 事件 JavaScript      更新时间:2023-09-26

我正在循环中的项目上创建JavaScript事件,但是每次触发事件时,它只会触发创建的最后一个事件。

JavaScript:

var dirLinks = document.getElementsByClassName("dirLink"),
    iframe   = document.getElementById("tmpImg");
showDir.addEventListener('click', showDirContent, false);
showImgs.addEventListener('click', showImgsContent, false);
for (var i = 0; i < dirLinks.length; i++) {
    var link = dirLinks[i];
    link.onclick = function () {
        updateIframeSource(link.getAttribute("imgSrc"));
    }
}
function updateIframeSource(source) {
    iframe.src = source;
}

.HTML:

<a class="dirLink" imgSrc="img1.jpg" href="#">img1.jpg</a><br />
<a class="dirLink" imgSrc="img2.jpg" href="#">img2.jpg</a><br />
<a class="dirLink" imgSrc="img3.jpg" href="#">img3.jpg</a><br />
<a class="dirLink" imgSrc="img4.jpg" href="#">img4.jpg</a><br />
<a class="dirLink" imgSrc="img5.jpg" href="#">img5.jpg</a>
<iframe id="tmpImg"></iframe>

无论我单击哪个链接,它都会点击传入img5.jpgupdateIframeSource函数。

这是因为在 javascript for loop 中不要在每次迭代中创建新作用域(只有函数会这样做),所以你在循环完成时执行的函数中引用一个变量link,所以它总是 5,要解决这个问题,只需将整个事情包装在匿名函数中,如下所示:

for(var i = 0; i < dirLinks.length; i++) {
    (function(link) {
        link.onclick = function () {
            updateIframeSource(link.getAttribute("imgSrc"));
        };
    })(dirLinks[i]);
}

这是因为循环不会创建新作用域。因为javascript有函数作用域:

var bindEvent = function(intId){
     var link = dirLinks[intId];
     link.onclick = function () {
            updateIframeSource(link.getAttribute("imgSrc"));
     }
}
for(var i = 0; i < dirLinks.length; i++) {
    bindEvent(i);
}

JSFIDDLE

也使用这个

for(var i = 0; i < dirLinks.length; i++) {
    var link = dirLinks[i];
    link.addEventListener("click", updateIframeSource());
}
function updateIframeSource() {
    return (function(event){
      iframe.src  = event.target.getAttribute("imgSrc");
      alert(iframe.src);
    });

}

分配事件处理程序的操作很昂贵,最好包装所有锚链接并使用事件委托:

具体方法如下:

<div id="container">
    <a class="dirLink" imgSrc="img1.jpg" href="#">img1.jpg</a><br />
    <a class="dirLink" imgSrc="img2.jpg" href="#">img2.jpg</a><br />
    <a class="dirLink" imgSrc="img3.jpg" href="#">img3.jpg</a><br />
    <a class="dirLink" imgSrc="img4.jpg" href="#">img4.jpg</a><br />
    <a class="dirLink" imgSrc="img5.jpg" href="#">img5.jpg</a>
</div>
<script>
var dirLinks = document.getElementsByClassName("dirLink");
var iframe = document.getElementById("tmpImg");
// Get the container
var container = document.getElementById("container");
//showDir.addEventListener('click', showDirContent, false);
//showImgs.addEventListener('click', showImgsContent, false);
container.addEventListener('click', function(evt){
    // You can send the event or extract like this the value of "imgsrc"
    updateIframeSource(evt.target.attributes.imgsrc.value);
});
function updateIframeSource(source) {
    iframe.src = source;
}
</script>

这是循环forEach另一种方式

.HTML:

  <a class="dirLink" imgSrc="img1.jpg" href="#">img1.jpg</a>
  <br />
  <a class="dirLink" imgSrc="img2.jpg" href="#">img2.jpg</a>
  <br />
  <a class="dirLink" imgSrc="img3.jpg" href="#">img3.jpg</a>
  <br />
  <a class="dirLink" imgSrc="img4.jpg" href="#">img4.jpg</a>
  <br />
  <a class="dirLink" imgSrc="img5.jpg" href="#">img5.jpg</a>
  <iframe id="tmpImg"></iframe>

.JS:

var dirLinks = document.getElementsByClassName("dirLink");
var iframe = document.getElementById("tmpImg");
[].forEach.call(dirLinks, (l) => {
  l.addEventListener('click', function() {
    updateIframeSource(l.getAttribute("imgSrc"));
  })
})
function updateIframeSource(source) {
  iframe.src = source;
}