我在使用某些 JavaScript 代码时遇到一些问题。 我想做的是将事件监听器添加到数组中的元素。
问题是,代码运行后,只有数组中的最后一个元素使事件监听器正常工作,其余元素返回错误。
我假设这是因为我在 for 循环和事件监听器中使用的逻辑。 什么是达到预期结果的有效方法?
function addSlider(config) {
var controls = `
<div id="next"> next </div>
<div id="previous"> previous </div>`;
var S_wrapper = config.wrapper;
var controls_html = document.createElement("div");
controls_html.setAttribute("id", "ctrl");
controls_html.innerHTML = controls;
var arrayData = config.wrapper.split(",");
for (i = 0; i < arrayData.length; i++) {
(function(index) {
document.querySelector(arrayData[i]).appendChild(controls_html);
var parent = document.querySelector(arrayData[index]);
console.log(i, index, arrayData[index], parent);
document.querySelector(arrayData[index]).addEventListener("mouseover", function(){
this.querySelector("#ctrl").style.display = "block";
})
document.querySelector(arrayData[index]).addEventListener("mouseout", function(){
this.querySelector("#ctrl").style.display = "none";
})
})(i);
}
}
最佳答案
有几个问题:
您在每次循环迭代中将相同的 div 移动到新的父级。您的
controls_html
不是 HTML,它是对HTMLDivElement
对象的引用。这一行:document.querySelector(arrayData[i]).appendChild(controls_html);
将它从它拥有的任何父级(最初没有,但在第一个循环之后,它是前一个循环中的元素)移动到新的父级。
如果您想在每个父级中都有一个新的
div
,则每次都需要创建一个新的div
。您在多个元素上使用相同的 ID,
ctrl
。这是无效的,ID 必须是唯一的。稍后,当您使用#ctrl
时,您将获得浏览器选择提供给您的任何元素(这是未指定的行为,尽管根据我的经验,它始终是第一个)。
所以我们需要处理这两个问题。采用对方法进行最小更改的解决方案,我们将 div 创建移至循环中并将索引添加到 ID:
function addSlider(config) {
var controls = `
<div id="next"> next </div>
<div id="previous"> previous </div>`;
var S_wrapper = config.wrapper;
var arrayData = config.wrapper.split(",");
for (i = 0; i < arrayData.length; i++) {
(function(index) {
var div = document.createElement("div");
div.setAttribute("id", "ctrl" + index);
div.innerHTML = controls;
var parent = document.querySelector(arrayData[index]);
parent.appendChild(div);
parent.addEventListener("mouseover", function() {
this.querySelector("#ctrl" + index).style.display = "block";
})
parent.addEventListener("mouseout", function() {
this.querySelector("#ctrl" + index).style.display = "none";
})
})(i);
}
}
但我会退后一步,看看更广阔的前景。例如,mouseover
和 mouseout
都会冒泡,因此您可以将它们挂接到父元素上并使用单个处理程序来处理它。也可能根本没有理由使用该 ID;我们可以用类或类似的类来标识子 div,并仅在 parent
中搜索它。您可以用 Array#forEach 替换循环及其中的函数。诸如此类的事情。
旁注:我注意到您正在使用模板文字(您分配给控件
的东西),这是ES2015(又名“ES6”)中引入的功能,但没有使用任何其他 ES2015 功能。因此,请标记这一点,以防您没有意识到......
关于javascript - 通过for循环添加事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43250765/