button.addEventListener无法在嵌套for循环

时间:2018-06-15 05:49:34

标签: javascript for-loop javascript-events nested

我正致力于为我制作的游戏创建地图文件的引擎。游戏是基于文本的冒险,它使用空格网格来显示消息,物品,任务,敌人等事件。

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

我正在使用此功能执行以下操作。

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 nest 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>";
        }

绝对没有任何行为。我不确定如何继续前进。 我对此有任何建议表示感谢。

谢谢。

1 个答案:

答案 0 :(得分:1)

问题在于:

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

但是如果你想让按钮在它自己的行上,最好把它放在一个块元素中,而不是追加br s:

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