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

将React二叉树动画迁移到Vue,是否可以在watcher中使用setInterval?

问题根因

你当前的实现出现异常确实和递归触发watch以及定时器滥用直接相关,核心问题有三个:

  • 你在time的监听回调中修改time的值,每次修改都会再次触发watch,进而源源不断创建新的setInterval实例,多个定时器同时累加time,自然会导致动画速度失控,和DELAY_IN_MS配置无关
  • 你没有对创建的定时器做清理逻辑,即便isUpdating变为false,之前创建的所有定时器依然会持续运行
  • 当isUpdating为false时,你给setInterval传入null作为间隔值,浏览器会自动使用最小延时(通常为4ms),进一步加快了time的累加速度

正确实现方案

你不需要监听time的变化,改为监听isUpdating状态来启停定时器即可,同时注意保存定时器ID方便清理:

Vue2 选项式API实现

data() {
  return {
    time: 0,
    isUpdating: false,
    timerId: null, // 保存定时器ID
    // 其余业务字段
    DELAY_IN_MS: 1000,
    maxTimes: 10,
    animate: true
  }
},
watch: {
  isUpdating(newVal) {
    // 状态变化时先清理旧定时器
    if (this.timerId) {
      clearInterval(this.timerId)
      this.timerId = null
    }
    if (newVal) {
      // 启动新定时器
      this.timerId = setInterval(() => {
        if (this.time >= this.maxTimes) {
          this.isUpdating = false
          return
        }
        this.time = this.animate ? Math.min(this.time + 1, this.maxTimes) : this.maxTimes
      }, this.DELAY_IN_MS)
    }
  }
},
// 组件卸载时清理定时器,避免内存泄漏
beforeDestroy() {
  if (this.timerId) {
    clearInterval(this.timerId)
  }
}

Vue3 组合式API实现(供参考)

import { ref, watch, onUnmounted } from 'vue'

const time = ref(0)
const isUpdating = ref(false)
const maxTimes = ref(10)
const animate = ref(true)
const DELAY_IN_MS = 1000
let timerId = null

watch(isUpdating, (newVal) => {
  if (timerId) {
    clearInterval(timerId)
    timerId = null
  }
  if (newVal) {
    timerId = setInterval(() => {
      if (time.value >= maxTimes.value) {
        isUpdating.value = false
        return
      }
      time.value = animate.value ? Math.min(time.value + 1, maxTimes.value) : maxTimes.value
    }, DELAY_IN_MS)
  }
})

onUnmounted(() => {
  if (timerId) clearInterval(timerId)
})

内容的提问来源于stack exchange,提问作者djangodev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:30:05