当前位置: 首页 > news >正文

在 Vue3 项目中实现定时刷新 vxe-table 数据,并在页面不可见时暂停刷新

在 Vue3 项目中实现定时刷新 vxe-table 数据,并在页面不可见时暂停刷新,可以通过以下方案实现:

方案一:使用 Page Visibility API + setInterval

<template><div><vxe-table:data="tableData":loading="loading"><!-- 表格列配置 --><vxe-column field="id" title="ID"></vxe-column><vxe-column field="name" title="名称"></vxe-column><vxe-column field="status" title="状态"></vxe-column></vxe-table></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { VxeTable, VxeColumn } from 'vxe-table'const tableData = ref([])
const loading = ref(false)
let refreshTimer = null
const refreshInterval = 10000 // 10秒// 获取表格数据
const fetchData = async () => {try {loading.value = true// 模拟API请求const response = await fetch('/api/your-data-endpoint')const data = await response.json()tableData.value = data} catch (error) {console.error('获取数据失败:', error)} finally {loading.value = false}
}// 启动定时刷新
const startAutoRefresh = () => {if (refreshTimer) {clearInterval(refreshTimer)}refreshTimer = setInterval(() => {if (!document.hidden) {fetchData()}}, refreshInterval)
}// 停止定时刷新
const stopAutoRefresh = () => {if (refreshTimer) {clearInterval(refreshTimer)refreshTimer = null}
}// 处理页面可见性变化
const handleVisibilityChange = () => {if (document.hidden) {// 页面不可见,停止刷新stopAutoRefresh()} else {// 页面可见,开始刷新startAutoRefresh()// 立即刷新一次数据fetchData()}
}onMounted(() => {// 初始加载数据fetchData()// 启动定时刷新startAutoRefresh()// 监听页面可见性变化document.addEventListener('visibilitychange', handleVisibilityChange)// 监听页面卸载window.addEventListener('beforeunload', stopAutoRefresh)
})onUnmounted(() => {// 清理定时器和监听器stopAutoRefresh()document.removeEventListener('visibilitychange', handleVisibilityChange)window.removeEventListener('beforeunload', stopAutoRefresh)
})
</script>

方案二:使用 Web Worker 实现更精确的定时

// utils/refreshWorker.js
let refreshTimer = null
let interval = 10000
let isPageVisible = trueself.onmessage = function(e) {const { type, data } = e.dataswitch (type) {case 'START':interval = data.interval || 10000startTimer()breakcase 'STOP':stopTimer()breakcase 'VISIBILITY_CHANGE':isPageVisible = data.visibleif (isPageVisible && !refreshTimer) {startTimer()}breakcase 'UPDATE_INTERVAL':interval = data.intervalif (refreshTimer) {stopTimer()startTimer()}break}
}function startTimer() {if (refreshTimer) returnrefreshTimer = setInterval(() => {if (isPageVisible) {self.postMessage({ type: 'REFRESH' })}}, interval)// 立即触发一次if (isPageVisible) {self.postMessage({ type: 'REFRESH' })}
}function stopTimer() {if (refreshTimer) {clearInterval(refreshTimer)refreshTimer = null}
}
<template><div><div class="refresh-controls"><span>刷新间隔:</span><select v-model="selectedInterval" @change="updateInterval"><option :value="5000">5秒</option><option :value="10000">10秒</option><option :value="30000">30秒</option></select><button @click="toggleAutoRefresh">{{ autoRefreshEnabled ? '停止' : '开始' }}自动刷新</button></div><vxe-table:data="tableData":loading="loading"><!-- 表格列配置 --></vxe-table></div>
</template><script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'const tableData = ref([])
const loading = ref(false)
const autoRefreshEnabled = ref(true)
const selectedInterval = ref(10000)let refreshWorker = null// 获取数据
const fetchData = async () => {try {loading.value = true// 这里替换为实际的API调用const response = await fetch('/api/data')const data = await response.json()tableData.value = data} catch (error) {console.error('获取数据失败:', error)} finally {loading.value = false}
}// 初始化Web Worker
const initWorker = () => {if (typeof Worker !== 'undefined') {refreshWorker = new Worker(new URL('../utils/refreshWorker.js', import.meta.url))refreshWorker.onmessage = (e) => {if (e.data.type === 'REFRESH') {fetchData()}}// 启动定时器refreshWorker.postMessage({type: 'START',data: { interval: selectedInterval.value }})}
}// 更新刷新间隔
const updateInterval = () => {if (refreshWorker) {refreshWorker.postMessage({type: 'UPDATE_INTERVAL',data: { interval: selectedInterval.value }})}
}// 切换自动刷新
const toggleAutoRefresh = () => {autoRefreshEnabled.value = !autoRefreshEnabled.valueif (refreshWorker) {if (autoRefreshEnabled.value) {refreshWorker.postMessage({type: 'START',data: { interval: selectedInterval.value }})} else {refreshWorker.postMessage({ type: 'STOP' })}}
}// 处理页面可见性
const handleVisibilityChange = () => {if (refreshWorker) {refreshWorker.postMessage({type: 'VISIBILITY_CHANGE',data: { visible: !document.hidden }})}
}onMounted(() => {// 初始加载数据fetchData()// 初始化Web WorkerinitWorker()// 监听页面可见性变化document.addEventListener('visibilitychange', handleVisibilityChange)// 监听窗口聚焦事件(可选)window.addEventListener('focus', () => {if (refreshWorker && autoRefreshEnabled.value) {refreshWorker.postMessage({type: 'VISIBILITY_CHANGE',data: { visible: true }})}})
})onUnmounted(() => {// 清理if (refreshWorker) {refreshWorker.terminate()refreshWorker = null}document.removeEventListener('visibilitychange', handleVisibilityChange)
})
</script>

方案三:使用 Vue Composition API 封装为可复用 Hook

// composables/useAutoRefresh.js
import { ref, onMounted, onUnmounted } from 'vue'export function useAutoRefresh(callback, options = {}) {const {interval = 10000,immediate = true,autoStart = true} = optionsconst isActive = ref(autoStart)const isPageVisible = ref(!document.hidden)let timer = null// 启动刷新const start = () => {if (timer) returnisActive.value = trueconst executeRefresh = () => {if (isActive.value && isPageVisible.value) {callback()}}// 立即执行一次if (immediate) {executeRefresh()}// 设置定时器timer = setInterval(executeRefresh, interval)}// 停止刷新const stop = () => {isActive.value = falseif (timer) {clearInterval(timer)timer = null}}// 处理页面可见性变化const handleVisibilityChange = () => {isPageVisible.value = !document.hidden}// 更新间隔时间const updateInterval = (newInterval) => {stop()options.interval = newIntervalif (isActive.value) {start()}}onMounted(() => {// 监听页面可见性变化document.addEventListener('visibilitychange', handleVisibilityChange)if (autoStart) {start()}})onUnmounted(() => {stop()document.removeEventListener('visibilitychange', handleVisibilityChange)})return {isActive,start,stop,updateInterval}
}
<template><div><div class="control-panel"><button @click="toggleAutoRefresh">{{ autoRefreshControls.isActive ? '暂停' : '继续' }}自动刷新</button><span>最后刷新时间: {{ lastRefreshTime }}</span></div><vxe-table :data="tableData"><!-- 表格列 --></vxe-table></div>
</template><script setup>
import { ref, computed } from 'vue'
import { useAutoRefresh } from '@/composables/useAutoRefresh'const tableData = ref([])
const lastRefreshTime = ref(null)// 获取数据
const fetchTableData = async () => {try {const response = await fetch('/api/table-data')tableData.value = await response.json()lastRefreshTime.value = new Date().toLocaleTimeString()} catch (error) {console.error('刷新数据失败:', error)}
}// 使用自动刷新Hook
const autoRefreshControls = useAutoRefresh(fetchTableData, {interval: 10000,immediate: true,autoStart: true
})// 切换自动刷新
const toggleAutoRefresh = () => {if (autoRefreshControls.isActive) {autoRefreshControls.stop()} else {autoRefreshControls.start()}
}
</script>

关键点总结

  1. 页面可见性检测:使用 document.hiddenvisibilitychange 事件
  2. 资源清理:在组件卸载时清除定时器和事件监听器
  3. 错误处理:在数据刷新时添加适当的错误处理
  4. 用户体验:提供手动控制自动刷新的开关
  5. 性能优化:页面不可见时停止定时器,减少不必要的请求

建议使用方案一作为基础实现,如果需要更复杂的控制或复用逻辑,可以考虑使用方案三的 Composition API 封装。

http://www.jsqmd.com/news/91906/

相关文章:

  • 25、定制gvim的滚动条、菜单和工具栏
  • 7个让你重新爱上阅读的理由:Readest如何拯救你的碎片化时间?
  • DDD从0到企业级:迭代式学习 (共17章)之 四
  • 9、UNIX系统文件管理与POSIX标准解析
  • 民宿平台管理|基于Java + vue民宿平台管理系统(源码+数据库+文档)
  • 打造企业级AI助手:LobeChat插件系统深度使用教程
  • 5步构建高效强化学习环境:从零掌握gym空间设计实战
  • 2025智能家居更新策略:3步规避风险+紧急回滚技巧
  • 27、Vim自动缩进与关键字补全功能详解
  • 10、深入探索Shell字符串操作符:功能、应用与技巧
  • 助农农商|基于Java+ vue助农农商系统(源码+数据库+文档)
  • OptiScaler终极使用教程:快速掌握游戏画质优化核心技术
  • 绿色算力革命:液冷技术如何让数据中心能耗降低 30% 以上?
  • 超市管理|基于Java+ vue超市管理系统(源码+数据库+文档)
  • 腾讯开源Hunyuan-7B:256K超长上下文+快慢思考重塑大模型应用边界
  • 11、Korn Shell 编程:整数运算与变量使用
  • 如何用3个步骤构建超越传统搜索引擎的向量数据库系统?
  • 二手物品交易|基于Java + vue二手物品交易系统(源码+数据库+文档)
  • 学生选课|基于Java + vue学生选课系统(源码+数据库+文档)
  • 第七十一篇:单元测试与集成测试:unittest, pytest深度实战与Python最佳实践
  • 18、Unix系统网络服务配置与接口配置指南
  • 如何解决2.5D游戏开发中的深度感知难题?实战案例深度剖析
  • 37、Vile编辑器:功能特性与使用指南
  • SSDTTime终极指南:轻松解决Hackintosh硬件兼容难题
  • 第七十二篇:CI/CD流水线:自动化测试与部署深度实战
  • 河北省秦皇岛市山海关区自建房设计公司哪家强?2025 最新评测排行榜 + 5 星企业推荐 - 苏木2025
  • 1、技术环境定制与程序获取指南
  • React Native Snap Carousel:打造沉浸式滑动展示体验的技术解析
  • 边缘 AI 算力爆发:手机、穿戴设备背后的本地智能支撑
  • 学校组织架构图在线设计 教学管理部门层级