【Vue3】从混乱到有序:我用 1 个 Vue Hooks 搞定大屏项目所有定时任务

前言

你是否也曾在大屏项目中陷入这样的困境:

  • 为了实时展示数据,页面里塞了十几个setInterval
  • 定时器清理不当导致内存泄漏,页面越用越卡
  • 切换页面后轮询还在疯狂请求,控制台报错刷屏
  • 想统一控制所有定时任务的启停,却要逐个修改代码

作为一个常年和数据大屏打交道的前端开发者,我太懂这种痛了。大屏项目往往需要同时维护 N 个定时任务(数据刷新、状态同步、心跳检测...),原生定时器 API 用起来不仅繁琐,还容易出各种幺蛾子。

今天就给大家分享一个我专门为大屏场景设计的usePolling Hooks,用它管理定时任务,效率直接翻倍!

为什么需要专门的轮询 Hooks?

先说说大屏项目的特殊性:

  1. 高频定时任务多:一个大屏可能需要同时维护 5-10 个不同的轮询任务(实时数据、告警、状态更新等)
  2. 资源敏感:大屏通常需要长时间运行,内存泄漏是致命问题
  3. 可见性需求:页面隐藏时没必要继续轮询(比如切换标签页)
  4. 统一管理:需要能批量控制所有轮询的启停状态

原生setInterval的问题就很明显了:每次使用都要手动管理定时器 ID、手动清理、手动处理异常,代码冗余且容易出错。

于是我封装了这个usePolling Hooks,把所有重复逻辑收归一处,让业务代码只关注核心逻辑。

核心实现:usePolling.ts

先上代码,核心逻辑不到 50 行,却解决了大屏轮询的所有痛点:

js 复制代码
import { ref, onMounted, onUnmounted } from "vue";

// interval: 轮询间隔时间,默认5分钟
export function usePolling(fn: () => void, interval: number = 5 * 60 * 1000) {
  const timer = ref<number | null>(null);
  const isActive = ref(true); // 页面可见性控制
  const isPolling = ref(false);
  const startPolling = () => {
    if (isPolling.value) return; // 防止重复启动
    isPolling.value = true;
    if (timer.value) clearInterval(timer.value); // 清理旧定时器
    // 设置新定时器
    timer.value = window.setInterval(async () => {
      if (!isActive.value) return; // 页面不可见时不执行
      try {
        await fn(); // 执行轮询任务(支持异步)
      } catch (error) {
        console.error("轮询异常:", error); // 统一错误处理
      }
    }, interval);
    fn(); // 立即执行一次(大屏通常需要即时数据)
  };
  // 页面可见性变化时自动暂停/恢复
  const handleVisibilityChange = () => {
    isActive.value = !document.hidden;
  };
  // 组件挂载时启动轮询并监听可见性变化
  onMounted(() => {
    document.addEventListener("visibilitychange", handleVisibilityChange);
    startPolling();
  });
  // 组件卸载时清理资源
  onUnmounted(() => {
    if (timer.value !== null) {
      clearInterval(timer.value);
    }
    document.removeEventListener("visibilitychange", handleVisibilityChange);
  });
  return { startPolling };
}

大屏项目中的实战用法

使用起来更是简单到离谱,只需要两步:

  1. 定义你的轮询任务(比如请求数据)
  2. usePolling包装它,指定间隔时间
js 复制代码
<template>
  <div class="dashboard">
    <!-- 大屏内容 -->
  </div>
</template>

<script setup lang="ts">
import { usePolling } from "./hooks/usePolling";
import { fetchRealTimeData } from "./api/dashboard";

// 1. 定义轮询任务:获取实时数据并更新视图
const fetchData = async () => {
  const data = await fetchRealTimeData();
  // 更新组件状态...
};

// 2. 使用轮询Hooks:每30秒刷新一次
const { startPolling } = usePolling(fetchData, 30 * 1000);

// 如需手动控制(比如按钮触发重启)
// const handleRestart = () => {
//   startPolling();
// };
</script>

如果页面有多个轮询任务,直接多次调用即可:

js 复制代码
// 任务1:每30秒刷新实时数据 
usePolling(fetchRealTimeData, 30 * 1000);
// 任务2:每5分钟同步一次配置 
usePolling(syncConfig, 5 * 60 * 1000); 
// 任务3:每10秒检测一次告警状态
usePolling(checkAlarm, 10 * 1000);

所有轮询都会自动遵守页面可见性规则,组件卸载时自动清理,再也不用手动管理一堆定时器了!

总结

usePolling Hooks的不足以及需要完善之处,大佬们可以在评论区指出

相关推荐
Byron07073 小时前
从 0 到 1 搭建 Vue 前端工程化体系:提效、提质、降本实战落地
前端·javascript·vue.js
哆啦code梦3 小时前
前端存储三剑客:localStorage、sessionStorage与Cookie解析
前端·前端存储
zhengfei6113 小时前
【AI平台】- 基于大模型的知识库与知识图谱智能体开发平台
vue.js·语言模型·langchain·知识图谱·多分类
徐小夕@趣谈前端3 小时前
Web文档的“Office时刻“:jitword共建版2.0发布!让浏览器变成本地生产力
前端·数据结构·vue.js·算法·开源·编辑器·es6
Data_Journal3 小时前
如何使用 Python 解析 JSON 数据
大数据·开发语言·前端·数据库·人工智能·php
德育处主任Pro3 小时前
纯前端网格路径规划:PathFinding.js的使用方法
开发语言·前端·javascript
墨笔.丹青3 小时前
基于QtQuick开发界面设计出简易的HarmonyUI界面----下
开发语言·前端·javascript
董世昌414 小时前
深度解析浅拷贝与深拷贝:底层逻辑、实现方式及实战避坑
前端·javascript·vue.js
扶苏10024 小时前
vue使用event.dataTransfer实现A容器数据拖拽复制到到B容器
前端·vue.js·chrome
David凉宸4 小时前
Vue 3 项目的性能优化策略:从原理到实践
前端·vue.js·性能优化