javascript - button.addEventListener 在嵌套 for 循环中不起作用

标签 javascript for-loop nested dom-events

我正在开发一种引擎,可以为我制作的游戏创建 map 文件。该游戏是一种基于文本的冒险游戏,它使用空间网格来显示消息、元素、任务、敌人等事件。

我现在正在处理的表单将使用按钮创建一个网格,因为将值输入到输入字段中 - 这会创建更好的视觉表示。

我正在研究执行以下操作的函数。

  1. 检查是否指定了高度 - 这样它就知道在执行任何其他操作之前绘制的是线性房间还是矩形房间

  2. 如果它是线性房间(仅指定了宽度),它会使用宽度来创建按钮并将其附加到包含元素。

  3. 如果它是矩形(已指定宽度和高度),则运行嵌套的 for 循环,为宽度附加 x 个按钮,然后为高度附加 y 个

  4. 单击其中一个按钮时,它会在屏幕上附加另一个表单。然后可以由用户填写。

代码如下:

    var creategridwidth = function(room)
{
    //store the room in a local variable
    var room = room;
    //while the grid container has children in it
    while(room.subGridContainer.hasChildNodes())
    {
        //remove the children from the container
        room.subGridContainer.removeChild(room.subGridContainer.lastChild);
    }
    //if the room height has already been set
    if(room.heightValue > 0)
    {
        //loop through the amount of rows
        for(var x = 0; x < room.heightValue; x ++)
        {
            //loop through the amount of columns
            for(var y = 0; y < room.widthValue; y ++)
            {
                //create a new button element
                var button = document.createElement('button')
                //assign the button element to the grid class
                button.setAttribute("class", "grid");
                //add an event listener for on click to view input information
                button.addEventListener('click', function() 
                {
                    console.log("click")
                    //run add space input function to add the html form to the page.
                    addspaceinput(room);
                }, false);
                //display the button as inline block so that they are side by side
                button.style.display = "inline-block";
                //append the button to the grid container
                room.subGridContainer.appendChild(button);                          
            }
            //when the row has been added, add a line break to start the next lie.
            room.subGridContainer.innerHTML += "<br>";
        }
    //if the height has not already been set
    } else {
        //loop through the width of the room
        for(var z = 0; z < room.widthValue; z ++)
        {
            //create a new button element
            var button = document.createElement('button')
            //assign the button element to the grid class
            button.setAttribute("class", "grid");
            //add an event listener for on click to view input information
            button.addEventListener('click', function() 
            {
                console.log("click")
                //run add space input function to add the html form to the page.
                addspaceinput(room);
            }, false);
            //display the button as inline block so that they are side by side
            button.style.display = "inline-block";
            //append the button to the grid container
            room.subGridContainer.appendChild(button);
        }
    }
}

现在,我遇到麻烦的部分是发生在嵌套 for 循环中的事件监听器。

例如:

        for(var z = 0; z < room.widthValue; z ++)
        {
            //create a new button element
            var button = document.createElement('button')
            //assign the button element to the grid class
            button.setAttribute("class", "grid");
            //add an event listener for on click to view input information
            button.addEventListener('click', function() 
            {
                console.log("click")
                //run add space input function to add the html form to the page.
                addspaceinput(room);
            }, false);
            //display the button as inline block so that they are side by side
            button.style.display = "inline-block";
            //append the button to the grid container
            room.subGridContainer.appendChild(button);
        }

我可以在控制台中看到此日志,效果很好。 然而:

        for(var x = 0; x < room.heightValue; x ++)
        {
            //loop through the amount of columns
            for(var y = 0; y < room.widthValue; y ++)
            {
                //create a new button element
                var button = document.createElement('button')
                //assign the button element to the grid class
                button.setAttribute("class", "grid");
                //add an event listener for on click to view input information
                button.addEventListener('click', function() 
                {
                    console.log("click")
                    //run add space input function to add the html form to the page.
                    addspaceinput(room);
                }, false);
                //display the button as inline block so that they are side by side
                button.style.display = "inline-block";
                //append the button to the grid container
                room.subGridContainer.appendChild(button);                          
            }
            //when the row has been added, add a line break to start the next lie.
            room.subGridContainer.innerHTML += "<br>";
        }

这完全没有任何行为。我不确定如何推进这个。 如果对此有任何建议,我将不胜感激。

最佳答案

问题出在这里:

room.subGridContainer.innerHTML += "<br>";

当您分配给 innerHTML 时,现有的 innerHTML 被检索,元素被清除,然后是新的连接的 innerHTML 字符串被解析为DOM。因此,任何引用内部元素的变量都将丢失,包括曾经具有事件监听器的元素。

const button = document.body.appendChild(document.createElement('button'));
button.textContent = 'click';
button.onclick = () => console.log('clicked');

// the next line will break the listener:
document.body.innerHTML += '<br>';

改为显式附加元素:

room.subGridContainer.appendChild(document.createElement('br'));

另一种选择是insertAdjacentHTML:

room.subGridContainer.insertAdjacentHTML('beforeend', '<br>');

但是如果你想让按钮独占一行,最好将它放在 block 元素中,而不是附加 brs:

var div = room.subGridContainer.appendChild(document.createElement('div'));
var button = div.appendChild(document.createElement('button'));
// etc

关于javascript - button.addEventListener 在嵌套 for 循环中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50869761/

相关文章:

javascript - HTML:输入按钮在繁忙的网页上卡住

java - GUI 类(JTextField-JTextArea)

c# - 为一组数字生成组合

Python:如何访问此类列表中的数据?

javascript - 如何在不添加浏览器的情况下打印 html

javascript - 如何根据光滑的轮播宽度有条件地添加下一个和上一个箭头?

c 8个硬币组合代码

c++ - 利用否则浪费的填充空间

Java Streams 在同一个列表上循环两次

javascript - 处理 keydown 事件中的某些键时遵循默认行为