【问题标题】:EventListener doesn't trigger second time when passing a named function but triggers normally when passing the complete functionEventListener 在传递命名函数时不会第二次触发,但在传递完整函数时会正常触发
【发布时间】:2022-01-14 14:25:35
【问题描述】:

我正在尝试为 etch-a-sketch 编写一个简单的函数,但遇到了这个问题。我将 eventListener 附加到颜色和擦除按钮上,如下所示:

eraseBtn.addEventListener("click", function erase(){
    document.addEventListener("mouseover", function eraser(event){
        let elem = event.target.closest('div');
        if (!elem || elem.parentNode.id != "container") return;
        elem.style.backgroundColor = "";
    });
});

coloringBtn.addEventListener("click", function color(){
    document.addEventListener("mouseover", function coloring(event) {
        let elem = event.target.closest('div');
        if (!elem || elem.parentNode.id != "container") return;
        let randColor1 = Math.round(Math.random() * 255);
        let randColor2 = Math.round(Math.random() * 255);
        let randColor3 = Math.round(Math.random() * 255);
        elem.style.backgroundColor = `rgb(${randColor1}, ${randColor2}, ${randColor3})`;
    });
});

此功能按预期运行,即,当我单击颜色时,您可以绘制颜色,并且通过单击擦除可以擦除您绘制的颜色。但是,此变体在第一次点击时有效,之后不再有效:

function erase(){
    document.addEventListener("mouseover", eraser);
}
function eraser(event){
        let elem = event.target.closest('div');
        if (!elem || elem.parentNode.id != "container") return;
        elem.style.backgroundColor = "";
    };
eraseBtn.addEventListener("click", erase);

function color(){
    document.addEventListener("mouseover", coloring);
};
function coloring(event) {
        let elem = event.target.closest('div');
        if (!elem || elem.parentNode.id != "container") return;
        let randColor1 = Math.round(Math.random() * 255);
        let randColor2 = Math.round(Math.random() * 255);
        let randColor3 = Math.round(Math.random() * 255);
        elem.style.backgroundColor = `rgb(${randColor1}, ${randColor2}, ${randColor3})`;
    };
coloringBtn.addEventListener("click", color);

这是第二种情况的工作演示: Codepen Link because SO snippet is not working for me.

为什么第二个没有按预期工作而第一个工作正常?

【问题讨论】:

  • 从其他事件监听器中添加事件监听器几乎总是是一个错误。
  • 作为一般规则,我会避免在其他事件中添加事件,因为它会变得混乱。使用例如设置变量控制鼠标移动结果的var mode = 'erase' 会更加可靠。
  • @Pointy 所以我们不应该将一个事件完全传递给另一个事件?
  • 该函数被称为add事件监听器。每次“点击”都会添加另一个鼠标悬停监听器。
  • @Pointy 我现在明白了。谢谢。

标签: javascript


【解决方案1】:

这里缺少的是remove event listeners 的能力。目前,鼠标悬停时可以同时进行擦除和着色。此外,一些用于跟踪状态的布尔值将有助于保证结果。

let erasingEnabled = false;
let coloringEnabled = false;

eraseBtn.addEventListener("click", function erase(){
    erasingEnabled = !erasingEnabled;

    if (erasingEnabled) {
        coloringEnabled = false;
        document.removeEventListener("mouseover", coloring);
        document.addEventListener("mouseover", eraser);
    } else {
        document.removeEventListener("mouseover", eraser);
        document.addEventListener("mouseover", coloring);
    }
});

coloringBtn.addEventListener("click", function color(){
    coloringEnabled = !coloringEnabled;

    if (coloringEnabled) {
        erasingEnabled = false;
        document.removeEventListener("mouseover", eraser);
        document.addEventListener("mouseover", coloring);
    } else {
        document.removeEventListener("mouseover", coloring);
        document.addEventListener("mouseover", eraser);
    }
});

function eraser(event){
    let elem = event.target.closest('div');
    if (!elem || elem.parentNode.id != "container") return;
    elem.style.backgroundColor = "";
}

function coloring(event) {
    let elem = event.target.closest('div');
    if (!elem || elem.parentNode.id != "container") return;
    let randColor1 = Math.round(Math.random() * 255);
    let randColor2 = Math.round(Math.random() * 255);
    let randColor3 = Math.round(Math.random() * 255);
    elem.style.backgroundColor = `rgb(${randColor1}, ${randColor2}, ${randColor3})`;
}

【讨论】:

    猜你喜欢
    • 2019-09-29
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    相关资源
    最近更新 更多