mousedown 事件显示 ctrlKey 的错误值

mousedown event showing wrong value for ctrlKey

提问人:Xerillio 提问时间:11/16/2023 更新时间:11/16/2023 访问量:32

问:

我正在摆弄鼠标后面的“工具提示”,并且仅在按住 ctrl 键时显示。为了减少对性能的影响,我只在按住 ctrl 键时订阅“mousemove”事件:

// Some initialization:
const tooltipElem = createTooltipElementInTheDom();
window.addEventListener("keydown", toggleTooltip);
window.addEventListener("keyup", toggleTooltip);
let listenerCounter = 0;

// ...

function toggleTooltip(ev) {
    const hideTooltip = !ev.ctrlKey;
    const shouldToggle = tooltipElem.hidden !== hideTooltip;
    if (!shouldToggle) {
        return;
    }

    // For performance, only listen for the mousemove event when the tooltip is shown
    if (hideTooltip) {
        window.removeEventListener("mousemove", handleMouseMove);
        console.log("Listener removed: " + --listenerCounter);
    }
    else {
        moveTooltip(0, 0); // Just sets x and y position
        window.addEventListener("mousemove", handleMouseMove);
        console.log("Listener added: " + ++listenerCounter);
    }

    tooltipElem.hidden = hideTooltip;
}

function handleMouseMove(ev) {
    moveTooltip(ev.clientX, ev.clientY + 20);

    // In case the window lost focus when we meant to toggle off the tooltip
    // let's check if we still want to show it. Otherwise, toggle it off.
    // This happens e.g. when pressing ctrl + f, causing the window to never receive a keyup event
    if (!ev.ctrlKey) { // <- this is where the problem occurs
        toggleTooltip(ev);
    }
}

如果我在按下 ctrl 键时四处移动鼠标,将按预期首先调用,然后立即调用,因为 - 也按预期。但是,in 为 true,而 in 为 false,这会导致控制台中的以下输出:toggleTooltiphandleMouseMoveaddEventListener("mousemove"...toggleTooltipev.ctrlKeyhandleMouseMove

Listener added: 1
Listener removed: 0
Listener added: 1

...然后没有更多的输出,直到我松开 ctrl 键。我只期望第一行,而最后一行必须来自这样一个事实,即在按住 ctrl 的同时,keydown 事件会连续触发(因此我的检查)。shouldToggle

为什么我会进入输出(真正的问题是它会导致显示工具提示的延迟)?有没有办法避免它,而没有包装在一个非常美妙的黑客中,并且仍然确保我尽快取消订阅mousemove?Listener removed: 0addEventListenersetTimeout

JavaScript 鼠标事件

评论

2赞 freedomn-m 11/16/2023
"我只在按住 ctrl 键时订阅“mousemove”事件“ - 添加/删除事件的性能可能不如始终侦听并检查第一行是否按下键。没有统计数据,只有“直觉”。当然,代码要少得多,复杂程度也要低得多!如果您担心更新过多,也许是该事件。debounce
0赞 freedomn-m 11/16/2023
function handleMouseMove(ev) { if (!ev.ctrlKey) { hideTooltip(); return; } .. show/move tooltip }
0赞 Xerillio 11/16/2023
@freedomn-m的“直觉”是基于什么?有没有理由相信添加/删除事件侦听器是一项如此繁重的操作,以至于在极少数情况下,即使有去抖动,ctrl-keydown/-up 也会超过每秒触发的 100 个 mousemove 事件 (?)?我很难相信后者不会消耗更多的 CPU 时间。不过,我确实同意这种复杂性。
2赞 Yogi 11/16/2023
我做了一个快速的性能测试。检查布尔值然后返回的事件处理程序需要 0.000005 秒。鼠标事件以 50 Hz 的频率触发。您可以在 0.0001 秒内添加和删除侦听器。因此,人们可能会得出结论,性能提升是微不足道的,添加/删除侦听器几乎没有价值。
1赞 freedomn-m 11/16/2023
@Xerillio “'直觉'是基于什么?”——根据定义:我的直觉

答: 暂无答案