You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:42:17