面试题:如何销毁 Vue 组件中的定时器?

在 Vue 组件中使用定时器(如 setTimeoutsetInterval)时,如果组件销毁时定时器未清除,可能会导致内存泄漏或意外行为。因此,需要在组件销毁时手动清除定时器。


1. beforeDestroybeforeUnmount 钩子中清除定时器

在 Vue 2 中,可以使用 beforeDestroy 钩子;在 Vue 3 中,可以使用 beforeUnmount 钩子。

Vue 2 示例

export default {
  data() {
    return {
      timer: null,
    };
  },
  mounted() {
    this.timer = setInterval(() => {
      console.log('Timer tick');
    }, 1000);
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer); // 清除定时器
      this.timer = null;
    }
  },
};

Vue 3 示例

import { onMounted, onBeforeUnmount } from 'vue';

export default {
  setup() {
    let timer = null;

    onMounted(() => {
      timer = setInterval(() => {
        console.log('Timer tick');
      }, 1000);
    });

    onBeforeUnmount(() => {
      if (timer) {
        clearInterval(timer); // 清除定时器
        timer = null;
      }
    });
  },
};

说明

  • mounted 钩子中创建定时器。
  • beforeDestroy(Vue 2)或 beforeUnmount(Vue 3)钩子中清除定时器。

2. 使用 clearTimeout 清除一次性定时器

如果使用的是 setTimeout,需要在组件销毁时调用 clearTimeout

示例

export default {
  data() {
    return {
      timer: null,
    };
  },
  mounted() {
    this.timer = setTimeout(() => {
      console.log('Timeout completed');
    }, 5000);
  },
  beforeDestroy() {
    if (this.timer) {
      clearTimeout(this.timer); // 清除定时器
      this.timer = null;
    }
  },
};

说明

  • setTimeout 创建一次性定时器,需要在组件销毁时清除。

3. 封装定时器逻辑

为了减少重复代码,可以将定时器逻辑封装到一个自定义 Hook 或 Mixin 中。

自定义 Hook(Vue 3)

import { onMounted, onBeforeUnmount } from 'vue';

export function useInterval(callback, delay) {
  let timer = null;

  onMounted(() => {
    timer = setInterval(callback, delay);
  });

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

使用示例

import { useInterval } from './useInterval';

export default {
  setup() {
    useInterval(() => {
      console.log('Timer tick');
    }, 1000);
  },
};

Mixin(Vue 2)

export const timerMixin = {
  data() {
    return {
      timer: null,
    };
  },
  methods: {
    startTimer(callback, delay) {
      this.timer = setInterval(callback, delay);
    },
    stopTimer() {
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      }
    },
  },
  beforeDestroy() {
    this.stopTimer();
  },
};

使用示例

import { timerMixin } from './timerMixin';

export default {
  mixins: [timerMixin],
  mounted() {
    this.startTimer(() => {
      console.log('Timer tick');
    }, 1000);
  },
};

说明

  • 通过封装逻辑,减少重复代码,提高可维护性。

4. 使用 watch 监听数据变化

如果定时器依赖于某个数据的变化,可以使用 watch 监听数据,并在数据变化时重新设置定时器。

示例

export default {
  data() {
    return {
      timer: null,
      count: 0,
    };
  },
  watch: {
    count(newVal) {
      if (this.timer) {
        clearInterval(this.timer);
      }
      this.timer = setInterval(() => {
        console.log('Count:', newVal);
      }, 1000);
    },
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  },
};

说明

  • watch 中监听数据变化,重新设置定时器。

5. 总结

在 Vue 组件中使用定时器时,需要在组件销毁时手动清除定时器,以避免内存泄漏和意外行为。以下是关键点:

  1. beforeDestroy(Vue 2)或 beforeUnmount(Vue 3)钩子中清除定时器
  2. 使用 clearIntervalclearTimeout 清除定时器
  3. 封装定时器逻辑:通过自定义 Hook 或 Mixin 减少重复代码。
  4. 使用 watch 监听数据变化:在数据变化时重新设置定时器。

通过合理管理定时器,可以确保组件的稳定性和性能!

THE END
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容