问题描述
我正在创建一个程序,当我点击“keyup”时计时器开始,当我点击“keydown”时停止,并在我下次点击“keydown”时重置计时器。
const Timer = () => {
const [timer,setTimer] = useState(0);
let state = 0;
let isFired = false;
const increment = useRef(null);
useEffect(() => {
window.addEventListener('keydown',(e) => {
if (isFired) {
if (e.code === 'Space' && state === 2) {
e.stopPropagation();
isFired = false;
handleReset();
}
if (e.code === 'Space' && state === 1) {
clearInterval(increment.current);
state = 2;
}
}
});
window.addEventListener('keyup',(e) => {
if (!isFired) {
if (e.code === 'Space' && state === 0) {
isFired = true;
state = 1;
handleStart();
}
}
});
return () => {
window.removeEventListener('keydown',handleReset);
window.removeEventListener('keyup',handleStart);
};
},[]);
const handleStart = () => {
increment.current = setInterval(() => {
// DON'T copY THIS BIT
setTimer((timer) => timer + 10);
},10);
};
const handleReset = () => {
clearInterval(increment.current);
setTimer(0);
state = 0;
};
// DON'T copY THIS BIT
const formatTime = () => {
console.log(timer);
const getMilliSeconds = `0${timer % 60}`.slice(-2);
const seconds = `${Math.floor(timer / 60)}`;
const getSeconds = `0${seconds % 60}`.slice(-2);
const getMinutes = `0${Math.floor(timer / 3600)}`.slice(-2);
// return `${getHours} : ${getMinutes} : ${getSeconds}`;
if (getMinutes === '00') {
return `${getSeconds}.${getMilliSeconds}`;
} else {
return `${getMinutes} : ${getSeconds} : ${getMilliSeconds} `;
}
};
// const formatTime = () => {
// // const milliSeconds = `0${}`;
// const seconds = `0${Math.floor(timer / 100)}`;
// const minute = `0${Math.floor(timer / 3600)}`.slice(-2);
// return `${minute}.${seconds}`;
// };
return (
<div className="Timer">
<h1>{formatTime()}</h1>
</div>
);
};
到目前为止我已经尝试过这个 它大部分时间都有效,但有时会出现故障 而且我知道时间格式不正确,增量也是错误的。有时它会在“keydown”上停止并在同一笔划中触发“keyup”,使其从零开始重置计时器我不完全知道它是否在同一笔划上触发 keyup 但似乎确实如此
解决方法
我检查了您的代码,发现它需要进行太多更改。
- 您仅将
state
和isFired
用作变量,但在重新渲染时需要它们的持久值。因此,这些必须是状态。 - 您没有取消绑定在
keyup
和keydown
上绑定的同一个侦听器。 - 根据您当前的代码,您的计时器将从第 1 个
keyup
开始,然后在下一个keydown
停止。现在,在下一个keydown
它将重置为 0,然后在keyup
,计时器再次从 0 开始。
我修改了您的代码并在此处看到了有效的更改,
https://codesandbox.io/s/xenodochial-shannon-im8zt?file=/src/App.js