1. 从传统定时器到现代响应式定时器

在前端开发实践中,我们常常需要处理需要延迟执行或周期性执行的操作。无论是页面初始化时的延迟加载、搜索框的防抖处理,还是轮播图的自动播放,都离不开定时器的精密控制。在传统的JavaScript方案中,我们习惯于直接使用setTimeoutsetInterval这些原生API,但它们存在一些痛点:

// 传统方式存在的问题示例
let timer = null

function startPolling() {
  timer = setInterval(() => {
    console.log('Polling...')
  }, 1000)
}

function stopPolling() {
  clearInterval(timer)
}

// 需要手动维护定时器引用
// 组件销毁时容易忘记清除定时器
// 难以动态控制间隔时间

VueUse提供的useTimeoutuseInterval组合式API完美解决了这些问题。它们通过与Vue的响应式系统深度集成,带来以下核心优势:

  • 自动化的定时器销毁管理
  • 响应式的参数动态更新
  • 直观的状态控制接口
  • 完整的TypeScript支持

2. VueUse环境搭建及基础配置

首先确保在Vue3项目中安装必要的依赖:

npm install @vueuse/core

创建基础的Vue组件结构:

<script setup>
import { useTimeout, useInterval } from '@vueuse/core'

// 响应式倒计时控制示例
const count = ref(60)
const { start, stop } = useInterval(() => {
  if (count.value <= 0) stop()
  else count.value--
}, 1000)
</script>

<template>
  <button @click="start">开始倒计时</button>
  <span>{{ count }}秒后重试</span>
  <button @click="stop">立即停止</button>
</template>

3. useTimeout深度解析

3.1 基本应用模式

<script setup>
import { useTimeout } from '@vueuse/core'

// 提交防抖控制
const searchQuery = ref('')
const isSearching = ref(false)

const { start, stop } = useTimeout(() => {
  isSearching.value = false
  console.log('执行搜索:', searchQuery.value)
}, 500)

watch(searchQuery, () => {
  isSearching.value = true
  stop() // 重置之前的计时器
  start() // 开始新的倒计时
})
</script>

3.2 动态参数配置

<script setup>
import { useTimeout } from '@vueuse/core'

// 响应式延迟时间配置
const delay = ref(2000)
const { isActive, start } = useTimeout(
  () => console.log('延时任务执行'),
  delay // 支持响应式参数
)

// 动态调整延迟
const changeDelay = () => {
  delay.value = Math.random() * 3000
  start()
}
</script>

4. useInterval高阶运用

4.1 基础循环任务

<script setup>
import { useInterval } from '@vueuse/core'

// 实时数据推送模拟
const messages = ref<string[]>([])
const interval = ref(3000)

const { isActive, pause, resume } = useInterval(
  () => {
    const timestamp = new Date().toLocaleTimeString()
    messages.value.push(`系统消息 ${timestamp}`)
  },
  interval,
  { immediate: true }
)
</script>

4.2 复杂周期任务

<script setup>
import { useInterval } from '@vueuse/core'

// 竞速动画控制
const position = ref(0)
const speed = ref(100)
const acceleration = ref(10)

const { start } = useInterval(
  () => {
    position.value += speed.value
    speed.value += acceleration.value
  },
  100,
  {
    controls: true,
    immediate: false
  }
)

// 动态速率调整
const boost = () => {
  speed.value *= 1.5
  acceleration.value += 5
}
</script>

5. 双定时器联动实战

<script setup>
import { useTimeout, useInterval } from '@vueuse/core'

// 用户活跃度监测系统
const active = ref(true)
const warningCount = ref(0)

// 15秒不活跃触发警告
const { start: startTimeout } = useTimeout(() => {
  active.value = false
}, 15000)

// 每30秒活跃检测
const { pause: pauseInterval } = useInterval(() => {
  if (!active.value) {
    warningCount.value++
    console.warn(`用户已不活跃,触发第${warningCount.value}次警告`)
  }
}, 30000)

// 用户交互处理器
const handleUserAction = () => {
  active.value = true
  warningCount.value = 0
  startTimeout() // 重新开始计时
}

// 绑定全局事件
onMounted(() => {
  window.addEventListener('mousemove', handleUserAction)
  window.addEventListener('keydown', handleUserAction)
  startTimeout()
})
</script>

6. 实战性能优化策略

6.1 懒加载模式

<script setup>
import { useTimeoutFn } from '@vueuse/core'

// 首屏优化:延迟加载大组件
const showHeavyComponent = ref(false)

useTimeoutFn(() => {
  import('./HeavyComponent.vue').then(module => {
    showHeavyComponent.value = true
  })
}, 3000)
</script>

6.2 复杂任务分时处理

<script setup>
import { useInterval } from '@vueuse/core'

// 大数据分片处理
const dataChunks = ref([...Array(1000).keys()])
const processedCount = ref(0)

const { start, stop } = useInterval(() => {
  if (dataChunks.value.length === 0) {
    stop()
    return
  }
  
  // 每次处理20条数据
  const processItems = dataChunks.value.splice(0, 20)
  processedCount.value += processItems.length
}, 50)
</script>

7. 工程化注意事项

  1. 内存泄漏防范:组件卸载时自动清除定时器,但要注意全局事件监听的移除
  2. 状态同步问题:定时器回调中使用响应式数据要确保最新值
  3. 精确性校准:浏览器后台时定时器可能出现延迟堆积
  4. 异常边界处理:在错误处理中增加定时器中断逻辑
  5. 动画场景优化:对于高频率定时器推荐使用requestAnimationFrame
<script setup>
import { onUnmounted } from 'vue'

// 安全使用示例
const { start, stop } = useInterval(/* ... */)

onUnmounted(() => {
  stop()
  // 此处添加其他资源清理逻辑
})
</script>

8. 最佳实践总结

在三个月的实际项目应用中,我们总结了以下经验模式:

  • 表单验证场景优先使用useTimeout实现防抖
  • 状态轮询采用useInterval配合暂停/继续控制
  • 复杂时序逻辑可混合使用两种定时器
  • 长流程任务要加入进度反馈机制
  • 敏感操作增加二次确认超时取消功能
<script setup>
// 重要操作安全确认模式
const confirmAction = ref(false)
const { start, stop } = useTimeout(() => {
  confirmAction.value = false
}, 5000)

const handleImportantAction = () => {
  confirmAction.value = true
  start()
}
</script>