如何将 eventListener 函数添加到具有唯一 ID 的元素?

How to add eventListener function to elements with unique id?

我有一些动态卡片:

并且我想将 eventListener 添加到所有播放按钮(它们的代码是):

<a href="link">
    <img src="play.svg">
    <audio src="myMusic.mp3"></audio>
</a>

当我点击“播放”时,它应该如下所示:

(它应该改变图像并且还应该播放音频)

到目前为止我的 JS 代码是:

<script>
var imgsPlay = document.getElementsByClassName('play-img-loop');
var audioPlayers = document.getElementsByClassName('audio-player');

window.onload = function() {
        for(var i = 0; i < imgsPlay.length; i++) {
            imgsPlay[i].addEventListener('click', function(event) {

                if(this.getAttribute('src') == "img/icons/play.svg") {
                    this.setAttribute('src', "img/icons/play_red.svg");
                    audioPlayers[i].play();

                } else if(this.getAttribute('src') == "img/icons/play_red.svg") {
                    this.setAttribute('src', "img/icons/play.svg");
                    audioPlayers[i].pause();
                }
                
            });
        }    
    }

</script>

(我可以手动完成,但是)不能动态。我该怎么做?

你需要委托!如果不是,那么你的问题只是 JavaScript closure inside loops – simple practical example

的骗局

这里我假设你有一个名为 cardContainer 的容器

我对 _red 表示播放或暂停有点困惑,所以更改下面的代码以匹配。您的示例 HTML 与您显示的代码不匹配,播放器和图像上没有 类,因此我假设您在实际代码中确实有这些

window.addEventListener('load', function() {
  document.getElementById('cardContainer').addEventListener('click', function(e) {
    const tgt = e.target;
    if (tgt.classList.contains('play-img-loop')) {
      const src = tgt.getAttribute('src');
      const running = src.includes('_red');
      const audioPlayer = tgt.closest('a').querySelector('audio');
      tgt.setAttribute('src', `img/icons/play$(running?'':'_red').svg`);
      if (running) audioPlayer.pause();
      else audioPlayer.play();
    }
  });
});

您的问题是对闭包的处理不正确。事件侦听器回调永远不会按照您编写的方式获得 i 的正确值。 i 的值将始终是触发事件时的最后一个。

最简单的解决方法是只为单次迭代的范围定义变量 i - 这就是 let 所做的。

    for(let i = 0; i < imgsPlay.length; i++) {
        imgsPlay[i].addEventListener('click', function(event) {

            if(this.getAttribute('src') == "img/icons/play.svg") {
             ...
    }    

有用参考:setTimeout in for-loop does not print consecutive values