javascript - 通过for循环添加事件监听器

标签 javascript

我在使用某些 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);
}

}

最佳答案

有几个问题:

  1. 您在每次循环迭代中相同的 div 移动到新的父级。您的 controls_html 不是 HTML,它是对 HTMLDivElement 对象的引用。这一行:

    document.querySelector(arrayData[i]).appendChild(controls_html);
    

    它从它拥有的任何父级(最初没有,但在第一个循环之后,它是前一个循环中的元素)移动到新的父级。

    如果您想在每个父级中都有一个新的 div,则每次都需要创建一个新的 div

  2. 您在多个元素上使用相同的 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);
    }
}

但我会退后一步,看看更广阔的前景。例如,mouseovermouseout 都会冒泡,因此您可以将它们挂接到父元素上并使用单个处理程序来处理它。也可能根本没有理由使用该 ID;我们可以用类或类似的类来标识子 div,并仅在 parent 中搜索它。您可以用 Array#forEach 替换循环及其中的函数。诸如此类的事情。

<小时/>

旁注:我注意到您正在使用模板文字(您分配给控件的东西),这是ES2015(又名“ES6”)中引入的功能,但没有使用任何其他 ES2015 功能。因此,请标记这一点,以防您没有意识到......

关于javascript - 通过for循环添加事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43250765/

相关文章:

javascript - 将 JSX 附加到 ReactJS 中的状态变量

javascript - 如果我在 UserControl 外部使用 "FindControl",我在 UserControl 内使用什么?

javascript - AngularJS - 我不明白为什么工厂总是未定义

javascript - SVG 文件中的 "onclick"事件

javascript - 如何从子弹出窗口中定位原始顶部窗口中的 iframe?

javascript - TypeScript 和带有动态添加功能的矩变换

javascript - 从下拉选择中选择特定选项时选中相应的复选框?

javascript - 回溯历史后 Firefox 中的 Ajax 调用缓存

javascript - 根据单选按钮输入加载动态内容

javascript - 将 <a href ="#id"> 传输到 JavaScript