插件窝 干货文章 Vue3组件实例未销毁:如何解决useDocumentVisibility导致的定时器泄漏问题?

Vue3组件实例未销毁:如何解决useDocumentVisibility导致的定时器泄漏问题?

timer 定时器 useDocumentVisib watchEffect 849    来源:    2025-03-23

在Vue 3中,使用useDocumentVisibility(或类似的钩子)来监听页面可见性变化时,可能会遇到组件实例未销毁导致的定时器泄漏问题。这是因为在组件销毁时,定时器没有被正确清除。以下是如何解决这个问题的步骤:

1. 确保在组件销毁时清除定时器

在Vue 3中,可以使用onUnmounted生命周期钩子来确保在组件销毁时清除定时器。

import { onMounted, onUnmounted, ref } from 'vue';
import { useDocumentVisibility } from '@vueuse/core';

export default {
  setup() {
    const isVisible = ref(true);
    let timer = null;

    const { visibilityState } = useDocumentVisibility();

    onMounted(() => {
      timer = setInterval(() => {
        if (visibilityState.value === 'visible') {
          // 执行一些操作
          console.log('页面可见,执行操作');
        }
      }, 1000);
    });

    onUnmounted(() => {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    });

    return {
      isVisible,
    };
  },
};

2. 使用watchEffectwatch来监听可见性变化

如果你希望在页面可见性变化时执行某些操作,可以使用watchEffectwatch来监听visibilityState的变化,并在变化时执行相应的逻辑。

import { watchEffect, onUnmounted, ref } from 'vue';
import { useDocumentVisibility } from '@vueuse/core';

export default {
  setup() {
    const isVisible = ref(true);
    let timer = null;

    const { visibilityState } = useDocumentVisibility();

    watchEffect(() => {
      if (visibilityState.value === 'visible') {
        // 页面变为可见时启动定时器
        timer = setInterval(() => {
          console.log('页面可见,执行操作');
        }, 1000);
      } else {
        // 页面变为不可见时清除定时器
        if (timer) {
          clearInterval(timer);
          timer = null;
        }
      }
    });

    onUnmounted(() => {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    });

    return {
      isVisible,
    };
  },
};

3. 使用onScopeDispose(如果适用)

如果你在setup函数中使用了watchEffectwatch,并且希望在组件销毁时自动清理副作用,可以使用onScopeDispose

import { watchEffect, onScopeDispose, ref } from 'vue';
import { useDocumentVisibility } from '@vueuse/core';

export default {
  setup() {
    const isVisible = ref(true);
    let timer = null;

    const { visibilityState } = useDocumentVisibility();

    const stopWatch = watchEffect(() => {
      if (visibilityState.value === 'visible') {
        timer = setInterval(() => {
          console.log('页面可见,执行操作');
        }, 1000);
      } else {
        if (timer) {
          clearInterval(timer);
          timer = null;
        }
      }
    });

    onScopeDispose(() => {
      stopWatch();
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    });

    return {
      isVisible,
    };
  },
};

总结

通过使用onUnmountedonScopeDispose生命周期钩子,可以确保在组件销毁时清除定时器,从而避免定时器泄漏问题。同时,使用watchEffectwatch来监听页面可见性变化,可以在页面状态变化时动态地启动或清除定时器。