Expo(React Native)如何检测用户上次点击等交互后的间隔时长
用户空闲交互检测实现方案
核心思路
全局维护最后一次用户交互的时间戳,统一监听全页面的用户操作事件更新时间戳,通过低频率轮询计算空闲时长,达到阈值时触发对应UI调整逻辑,全程做好性能优化避免影响页面正常运行。
落地步骤
- 初始化基础状态:定义空闲时长阈值(如10000ms)、检测轮询间隔(推荐1000ms)、最后交互时间戳、空闲状态标记、定时器引用
- 绑定全量交互事件:在
document上绑定click、scroll、mousemove、keydown、touchstart、touchmove事件,覆盖PC、移动端所有常见用户操作,事件配置加passive: true避免阻塞页面默认行为。注意不要给单个业务组件重复绑定事件,统一绑定在全局即可,能大幅减少事件监听器数量 - 事件回调做节流处理:针对高频触发的
scroll、mousemove事件加200ms节流,每次触发事件时更新最后交互时间戳,如果当前处于空闲状态,立刻触发UI恢复逻辑 - 轮询检测状态:每间隔1秒计算当前时间与最后交互时间的差值,差值超过空闲阈值时触发降透明度等空闲UI逻辑,标记当前为空闲状态避免重复触发
- 边界场景处理:监听
visibilitychange事件,页面切到后台时清空检测定时器停止检测,页面切回前台时重置最后交互时间、重启检测;页面卸载时移除所有事件监听、清空定时器,避免内存泄漏
可复用代码实现
class IdleDetector { constructor(options = {}) { this.idleThreshold = options.idleThreshold ?? 10000; this.checkInterval = options.checkInterval ?? 1000; this.onIdle = options.onIdle || (() => {}); this.onActive = options.onActive || (() => {}); this.lastActiveTime = Date.now(); this.isIdle = false; this.checkTimer = null; this.throttleTimer = null; this.activeEvents = ['click', 'scroll', 'mousemove', 'keydown', 'touchstart', 'touchmove']; } #updateActiveTime() { if (this.throttleTimer) return; this.throttleTimer = setTimeout(() => { this.lastActiveTime = Date.now(); this.throttleTimer = null; if (this.isIdle) { this.isIdle = false; this.onActive(); } }, 200); } #checkIdleStatus() { const currentIdleDuration = Date.now() - this.lastActiveTime; if (currentIdleDuration >= this.idleThreshold && !this.isIdle) { this.isIdle = true; this.onIdle(); } } #handleVisibilityChange() { if (document.hidden) { this.stop(); } else { this.lastActiveTime = Date.now(); this.start(); } } start() { this.activeEvents.forEach(eventName => { document.addEventListener(eventName, this.#updateActiveTime.bind(this), { passive: true }); }); document.addEventListener('visibilitychange', this.#handleVisibilityChange.bind(this)); this.checkTimer = setInterval(this.#checkIdleStatus.bind(this), this.checkInterval); } stop() { this.activeEvents.forEach(eventName => { document.removeEventListener(eventName, this.#updateActiveTime.bind(this)); }); document.removeEventListener('visibilitychange', this.#handleVisibilityChange.bind(this)); clearInterval(this.checkTimer); clearTimeout(this.throttleTimer); this.checkTimer = null; this.throttleTimer = null; } } // 业务使用示例 const uiContainer = document.querySelector('.app-container'); const idleDetector = new IdleDetector({ idleThreshold: 10000, onIdle: () => { uiContainer.style.opacity = '0.5'; }, onActive: () => { uiContainer.style.opacity = '1'; } }); // 页面加载完成后启动检测 idleDetector.start(); // 页面卸载时调用 idleDetector.stop() 做清理
适配说明
- React/Vue等框架场景:将初始化、清理逻辑对应放到组件挂载/卸载生命周期中,需要操作的UI节点用框架提供的ref获取即可,核心逻辑无需修改
- 多梯度UI调整需求:如果需要按不同空闲时长做不同UI反馈(如5秒轻微降透明度、10秒大幅降透明度、30秒显示屏保),直接在
#checkIdleStatus方法中增加对应时长的判断分支即可 - 不需要额外引入第三方库,原生实现体积不到1KB,性能远高于开源的空闲检测插件
内容的提问来源于stack exchange,提问作者Srki
相关产品推荐
相关产品推荐

