React中实现触摸启动、释放停止的持续执行定时器方案
解决方案:React中实现触摸按住持续执行、移动不中断的逻辑
核心思路
用React的useRef保存定时器ID,在touchstart时启动定时器,touchend/touchcancel时清除定时器,touchmove中仅处理移动逻辑、不中断定时器运行,以此实现类似秒表的按住计时、松开停止、移动不中断的效果。
代码示例
import { useRef, useState } from 'react'; function TouchStopwatch() { const [time, setTime] = useState(0); // 用ref持久化定时器ID,避免组件重渲染丢失引用 const intervalRef = useRef(null); // 持续执行的目标函数(这里以计时为例) const tick = () => { setTime(prev => prev + 1); }; // 触摸开始:启动定时器 const handleTouchStart = () => { if (!intervalRef.current) { intervalRef.current = setInterval(tick, 1000); } }; // 触摸结束/意外中断:停止定时器 const handleTouchEnd = () => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } }; // 触摸移动:仅处理移动逻辑,不干扰定时器 const handleTouchMove = (e) => { // 这里可添加触摸点移动的处理逻辑,比如获取坐标 const touch = e.touches[0]; console.log(`触摸点位置:x=${touch.clientX}, y=${touch.clientY}`); // 可选:如果需要阻止页面滚动干扰触摸,可添加下面一行 // e.preventDefault(); }; return ( <div onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd} onTouchCancel={handleTouchEnd} onTouchMove={handleTouchMove} style={{ width: '200px', height: '200px', backgroundColor: '#f0f0f0', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '32px', userSelect: 'none' }} > {time}s </div> ); } export default TouchStopwatch;
关键细节说明
- 用
useRef存储定时器ID:组件重渲染时useRef的.current值不会重置,能确保始终拿到正确的定时器引用,避免无法清除或重复创建定时器。 - 处理
touchcancel事件:当触摸被意外中断(比如来电、系统弹窗)时,也能及时停止定时器,防止内存泄漏。 touchmove不碰定时器:这是保证移动不中断的核心,仅在该事件中处理移动相关逻辑即可。- 默认行为按需控制:如果不需要页面滚动,在
touchmove中调用e.preventDefault()可避免滚动干扰;若需要滚动则跳过该操作。
原问题失效原因分析
你之前的setInterval失效,大概率是这两个原因:
- 没有用
useRef持久化定时器ID,组件重渲染后丢失了定时器引用; - 误在
touchmove事件中执行了清除定时器的逻辑,导致移动时中断了函数执行。
内容的提问来源于stack exchange,提问作者marco trevi
相关产品推荐
相关产品推荐

