首页 > 解决方案 > type=button 的 addEventListener 只工作一次

问题描述

我正在做一个作业,用户可以在 n*n 网格内绘制。任务如下:

我的问题: 我坚持最后一项任务。2个按钮工作得很好。但是它们只能被调用一次。如果我选择黄色 - 它会绘制黄色。如果我然后选择灰色 - 它会绘制灰色。之后,按钮单击不再执行任何操作,但我仍然可以绘制灰色。

这就是我到目前为止所做的: 首先,我查询选择了按钮类型并添加了一个 EventListener“点击”。

其次,在 colourHover 函数中,根据按钮的 ID 调用 mouseover EventListener。

第三,EventListener-mouseover 在各自的函数 ( grayColour(event), yellowColour(event)) 中定义。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body id="start">
<div class="container" id="grid">
</div>
<div><button type="button" class="button" id="gray">Gray Colour</button></div>
<div><button type="button" class="button" id="yellow">Yellow Colour</button></div>
<div><button type="button" id="button">Resize your grid manually.</button></div>

<script>
"use strict";

let container = document.getElementById("grid");
let n;

// creating a grid with number-input from user.
let makeGrid = function makeGrid(input) {
    let c;
    
    for (c = 0; c < (input * input); c++) {
        let cell = document.createElement("div");
        container.appendChild(cell).className = "squares";
        
    };
    container.style.gridTemplateColumns = `repeat(${input}, auto)`;
    container.style.gridTemplateRows = `repeat(${input}, auto)`;
};

// function gets exectuted, only if a number and below 101
let numberCheck = function numberCheck() {
    
    if ((n % n) === 0 && n <= 100) {
    makeGrid(n);
};

    while ((n % n) !== 0) {
        alert("Please enter a number.");
        n = prompt("Choose again.");
        if ((n % n) === 0 && n <= 100) {
            makeGrid(n);
        }
    };

    while ((n % n) === 0 && n > 100) {
        alert("The number is too high.");
        n = prompt("Choose again.");
        if ((n % n) === 0 && n <= 100) {
            makeGrid(n);
        }
        else if ((n % n) !== 0) {
            alert("Please enter a number");
            n = prompt("Choose again");
                if ((n % n) === 0 && n <= 100) {
                    makeGrid(n);
                }
        }
    };
    
};

// default grid on first pageload
makeGrid(16);

// this function sets the hovered items colour to black on default / first pageload
let blackColor = function blackColor(event) {
    let colour = event.target;
    if (colour.className === "container") {
        return;
    }
    else if (colour.className === "squares") {
        colour.style.backgroundColor = "black";
    };
};

// addEventListener for blackColor function
let hoverItems = document.querySelectorAll(".container");
    hoverItems.forEach(element => { element.addEventListener("mouseover", blackColor)
});



// function to manual selecting a grid-size. Beforehand, old grid gets deleted
let removeElements = function removeElements(event) {
    let elements = document.getElementsByClassName("squares");
    while (elements.length > 0) {
        elements[0].parentNode.removeChild(elements[0]);
    };
    n = prompt("Choose the size of your grid");
    numberCheck(n);
};

// button for selecting a grid-size manually
let button = document.querySelector("#button");
button.addEventListener("click", removeElements);


// this function sets the background-color of the cells on mouseover to gray
let grayColour = function grayColour(event) {
        let colour = event.target;
        if (colour.className === "container") {
        return;
    }
    else if (colour.className === "squares") {
        colour.style.backgroundColor = "gray"

    }
}
// this function sets the background-color of the cells on mouseover to yellow
let yellowColour = function yellowColour(event) {
    let colour = event.target;
    if (colour.className === "container") {
        return;
    }
    else if (colour.className === "squares") {
    colour.style.backgroundColor = "yellow";

}
}


let colourHover = function colourHover(event) {
    let hover = document.querySelectorAll(".container");
    switch (event.target.id) {
        case "gray":
            //hover.forEach(element => { element.removeEventListener("mouseover", yellowColour)
            //});
            //hover.forEach(element => { element.removeEventListener("mouseover", grayColour)
            //});
            hover.forEach(element => { element.addEventListener("mouseover", grayColour)
        });
        break;
        case "yellow":
        //hover.forEach(element => { element.removeEventListener("mouseover", yellowColour)
            //});
            //hover.forEach(element => { element.removeEventListener("mouseover", grayColour)
            //});
        hover.forEach(element => { element.addEventListener("mouseover", yellowColour)
        });
        break;
};
};

let colourBtn = document.querySelectorAll(".button");
colourBtn.forEach(element => { element.addEventListener("click", colourHover)
});
</script>



</body>
</html>

我很欣赏任何正确方向的提示。现在真的卡住了。

标签: javascriptaddeventlistener

解决方案


最简单的方法是使用 CSS 类来设置单元格的样式,并在按钮单击处理程序中更改表格主体的类。“小部件”的状态应该存储在 JS 变量中,这样可以避免每次单击按钮时不必要的 DOM 遍历。像这样的东西:

const buttons = document.querySelectorAll('button'),
    table = document.querySelector('.hovered-colors');
// The state of the widget
let currentColor = 'black';

buttons.forEach(button => {
  button.addEventListener('click', e => {
    const newColor = e.target.getAttribute('data-color');
    table.classList.remove(currentColor);
    table.classList.add(newColor);
    currentColor = newColor;
  });
});
.black td:hover {
  color: white;
  background-color: black;
}

.gray td:hover {
  color: black;  
  background-color: gray;
}

.yellow td:hover {
  color: black;  
  background-color: yellow;
}
<table>
  <tbody class="hovered-colors black">
    <tr><td>R1C1</td><td>R1C2</td></tr>
    <tr><td>R2C1</td><td>R2C2</td></tr>
    <tr><td>R3C1</td><td>R3C2</td></tr>
  </tbody>
</table>

<button data-color="gray">Gray</button>
<button data-color="yellow">Yellow</button>


推荐阅读