我一直在为这个问题苦苦挣扎。在在这里创建这篇文章之前,我在整个社区中进行了搜索,并且在 React 中看到了很多针对长按事件的解决方案,但每个人都只解决了单击按钮事件。
我正在为魔方制作一个秒表。我需要做的是以下步骤:
P.S-1 : 如果秒表没有运行并且用户只需按空格键(不按住),则不会发生任何事情!仅当用户按住空格键至少两秒然后然后释放它时,秒表才会启动。
现在,我的问题是我应该查看的所有事件(开始和停止)都在 JavaScript 中的“keydown”和“keyup”侦听器下。我已经尝试了很多不同的解决方案来管理 JS 中的超时本机函数,但正如我所说,如果秒表停止并且用户只需按空格键,我不应该执行任何操作。
我尝试使用 useState 和 useRef 钩子来控制超时并检查空格键是刚刚按下还是长按。再说一遍,我的问题是一旦这两个事件处于“keydown”侦听器下,我不知道如何管理它。
我希望你们能帮助我,这意义重大!
提前谢谢您。
P.S-2:我正在使用 TypeScript!
编辑: 我忘记了 keydown 在按住时会触发多次,请查看下面的示例,只需检查该键是否是“重复”键。我必须使用 useRef 才能使其正常工作,但应该为其余逻辑奠定良好的基础:
const timestamp = useRef(0);
const spacebarPress = (e) => {
// exit if the key is not spacebar or is the same key as last pressed
if (e.keyCode !== 32 || e.repeat) return;
timestamp.current = Date.now();
}
const spacebarRelease = (e) => {
if (e.keyCode !== 32) {
return; // exit if the key is not spacebar
}
const pressed = timestamp.current, released = Date.now();
if (released - pressed < 2000)
return; // less than 2 seconds have passed since pressing
// ... your logic here, spacebar was pressed for two seconds.
}
我通常倾向于尽可能避免 setTimeout,在我看来,它不是很可靠并且调试起来很痛苦。
应该可以帮助您完成大部分工作,只需在计时器运行时添加不同的按键按下/按下事件,如果
e.repeat
阻止计时器再次暂停。
我正在尝试使用以下代码解决这个问题:
useEffect(() => {
document.addEventListener("keydown", handleKeyDown);
document.addEventListener("keyup", handleKeyUp);
return () => {
removeEventListener("keydown", handleKeyDown);
removeEventListener("keyup", handleKeyUp);
};
}, []);
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key !== " ") {
return;
}
timeRef.current = Date.now();
setTimestamp(Date.now());
};
const handleKeyUp = (e: KeyboardEvent) => {
if (e.key !== " ") {
return;
}
const pressed = timestamp;
const released = Date.now();
if (released - pressed < 2000) {
return;
}
};
由于某种原因,时间戳状态始终为 0(默认状态)。我尝试过使用 useRef 代替,但它也不起作用。
你最终弄清楚了吗?