使用 addEventListener 和 getElementsByClassName 传递元素 id

26

我正在从JSON文件中定义一个项目列表,并在网页上显示该列表。意图是让用户单击列表中的任何项目以显示有关该项目的更多信息(该信息保存在同一JSON文件中)。

该列表的所有项目都是同一类的成员,每个项目都有一个从JSON文件中定义的唯一ID。HTML看起来像这样:

<ul>
   <li class="menu" id="bob">Robert Smith</li>
   <li class="menu" id="jane">Jane Doe</li>
   <li class="menu" id="sue">Susan Carter</li>
</ul>

我原本计划使用类似以下的代码:

var userSelection = document.getElementsByClassName('menu');

结合以下代码:

userSelection.addEventListener('click', myFunctionToPrintDetails());

但我不确定如何将事件监听器中获取的id传递给打印函数,以便确定要打印哪些详细信息。

我在HTML/CSS方面有很多经验,但对JSON/AJAX了解甚少,所以可能我完全搞错了。如果有更合适的方法可以完成这项任务,欢迎提供反馈。

我尝试了两种答案,但都没有起作用。当我将userSelection.length记录到控制台时,得到的是0;当我记录userSelection时,输出为空。

HTMLCollection(0)
> sue: li#sue.menu
length: 3
> jane: li#jane.menu
> bob: li#bob.menu
> 0: li#bob.menu
> 1: li#jane.menu
> 2: li#sue.menu

1
将监听器添加到userSelection集合中的每个元素。使用函数名称myFunctionToPrintDetails添加监听器,而不是调用该函数。在处理程序内,被点击的元素是this值,假设您没有为处理程序使用lambda表达式(箭头函数)。 - traktor
5个回答

22

codepen演示

var userSelection = document.getElementsByClassName('menu');

for(var i = 0; i < userSelection.length; i++) {
  (function(index) {
    userSelection[index].addEventListener("click", function() {
       console.log("Clicked index: " + index);
     })
  })(i);
}

正如评论中@torazaburo所指出的,如果你想要支持符合ECMAScript 6(ES6)标准的浏览器,可以使用以下方法。

var userSelection = document.getElementsByClassName('menu');

for(let i = 0; i < userSelection.length; i++) {
  userSelection[i].addEventListener("click", function() {
    console.log("Clicked index: " + i);
  })
}

2
index 定义在哪里?循环结束后它的值是多少? - traktor
1
仍然存在“臭名昭著的JavaScript循环问题” - 当单击发生时,i被设置为userSelection.length。请参见https://dev59.com/v3RB5IYBdhLWcg3wAjNH。 - traktor
谢谢指出,你是对的。我添加了一个IIFE来解决这个问题。 - Der
1
你确定在调用 var userSelection = document.getElementsByClassName('menu'); 之前已经调用了吗?如果是这样,请将你的结果与我的解决方案的 codepen 实现 进行比较。 - Der
3
使用let关键字就不必在循环中使用IIFE的那一套麻烦步骤了。 - user663031
显示剩余3条评论

7

这是我会这么做的。首先,我会使用对象值创建一个数组。

const userSelection = Object.values(document.getElementsByClassName('menu'));

然后我会使用foreach循环遍历它们。
userSelection.forEach(link => {
    link.addEventListener(event => {
        event.preventDefault();
        // more code here
    });
});

轻松易懂!

使用Array.from相同的方法 Array.from(document.getElementsByClassName('menu')).forEach((elem) => { elem.addEventListener("click", (e) => {}); }); - undefined
1
addEventListener 需要 2 个参数,但只提供了第 2 个参数。应该在箭头函数之前提供要处理的事件。 - undefined

6

您可以通过this.id从响应点击事件的元素中获取id:

var items = document.getElementsByClassName('menu');
for (var i = 0; i < items.length; i++) {
  items[i].addEventListener('click', printDetails);
}

function printDetails(e) {
  console.log("Clicked " + this.id);
}
<ul>
   <li class="menu" id="bob">Robert Smith</li>
   <li class="menu" id="jane">Jane Doe</li>
   <li class="menu" id="sue">Susan Carter</li>
</ul>


我尝试了两种解决方案,但都没有进展。当我将userSelection.length打印到控制台时,我得到的是0,但是当我打印userSelection时,我得到的是:HTMLCollection(0) > sue: li#sue.menu length: 3 > jane: li#jane.menu > bob: li#bob.menu > 0: li#bob.menu > 1: li#jane.menu > 2: li#sue.menu - Michael

0
这是我一直在使用的简短版本:
[...(document.getElementsByClassName('__MYCLASSNAME__'))].forEach(d => {
  d.addEventListener('click', MYFUNCTION__);
})

0
<ul id = "menuList">
   <li class="menu" id="bob">Robert Smith</li>
   <li class="menu" id="jane">Jane Doe</li>
   <li class="menu" id="sue">Susan Carter</li>
</ul>


// JS - Event Bubbling
const menuList= document.getElementById("menuList");
menuList.addEventListener("click", function (e) {
        console.log(e.target); // log clicked element 
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接