Javascript 通过for循环添加事件侦听器

Javascript 通过for循环添加事件侦听器,javascript,Javascript,我对一些JavaScript代码有一些问题。 我试图做的是向数组中的元素添加事件侦听器 问题是,在运行代码后,只有数组中的最后一个元素使eventlistener工作,其余元素返回错误 我假设这是因为我在for循环和eventlisteners中使用的逻辑。 实现预期结果的有效方法是什么 function addSlider(config) { var controls = ` <div id="next"> next </div> <

我对一些JavaScript代码有一些问题。 我试图做的是向数组中的元素添加事件侦听器

问题是,在运行代码后,只有数组中的最后一个元素使eventlistener工作,其余元素返回错误

我假设这是因为我在for循环和eventlisteners中使用的逻辑。 实现预期结果的有效方法是什么

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);
}

}PS:我将回答您当前代码中的问题,而不是讨论其他人已经对此发表评论的设计/重构

您的主要问题是使用id而不是类。请记住,文档中只能存在一个id,否则无法引用它们

此外,如果您也在重用controls_html元素,则应该为要添加到的每个元素创建一个新的控件。同样,在这种情况下

我已经创建了一个包含您代码的工作副本的

函数addSliderconfig{ 变量控制=` 下一个 以前的`; var S_wrapper=config.wrapper; var arrayData=config.wrapper.split,; 对于i=0;i有几个问题:

在每次循环迭代中,您都将相同的div移动到新的父级。您的控件\u html不是html,它是对HtmlLevel对象的引用。这一行:

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,并且只在父类中搜索它。可以用ArrayforEach替换循环及其内的函数。诸如此类的事情


旁注:我注意到您正在使用一个模板文字来指定控件,这是ES2015又称ES6中引入的一个功能,但没有使用任何其他ES2015功能。如果您没有意识到…

您是否考虑过将事件侦听器添加到所有渲染arrayData的父节点,以便每个元素只需要一个处理程序,而不是相同的处理程序?但是是的,你的问题是一个与关闭相关的问题,我会设法找到重复的。