Vue组件封装后onMounted调用定时器未触发的解决方法
解决Vue3封装倒计时组件后定时器不触发的问题
你的倒计时组件封装后定时器看似不工作,核心问题出在直接绑定只读props以及响应式处理不当,以下是具体解决方案:
问题根源
- 使用
toRef(props, 'time')绑定props:Vue的props是只读的,虽然toRef能保留响应式,但直接修改counter.value会违反单向数据流规则,导致视图无法正常更新,看起来像定时器没触发。 - 未清理定时器:组件卸载后定时器可能继续运行,同时如果父组件更新props,旧定时器不会被终止,引发逻辑混乱。
clearError函数可能未正确引入:如果这个函数是外部全局或模块导出的,未在组件内导入会导致报错,中断定时器逻辑。
修复后的完整代码
<template> {{ counter }} </template> <script setup lang="ts"> import { ref, onMounted, onUnmounted, watch } from 'vue'; // 若使用Vue Router做重定向,需导入router实例 // import router from '@/router'; const props = defineProps<{ time: number; }>(); // 用本地响应式变量存储倒计时数值,而非直接绑定props let counter = ref(props.time); // 保存定时器ID,用于后续清理 let timerId: number | null = null; const counterFunc = () => { timerId = setInterval(() => { counter.value--; if (counter.value <= 0) { // 倒计时结束后先清理定时器 clearInterval(timerId!); // 执行重定向逻辑,确保clearError可访问(或替换为实际跳转方式) // clearError({ redirect: '/' }); // 示例:原生JS跳转 window.location.href = '/'; // 示例:Vue Router跳转 // router.push('/'); } }, 1000); }; onMounted(() => { counterFunc(); }); // 组件卸载时清理定时器,避免内存泄漏 onUnmounted(() => { if (timerId) clearInterval(timerId); }); // 监听父组件传递的time变化,重置倒计时 watch(() => props.time, (newTime) => { counter.value = newTime; if (timerId) clearInterval(timerId); counterFunc(); }); </script>
关键修改说明
- 替换
toRef为ref:将props的time值复制到本地响应式变量counter,这样修改counter.value既符合单向数据流,又能正常触发视图更新。 - 添加定时器清理:在
onUnmounted钩子中清除定时器,防止组件卸载后定时器继续运行;同时监听props变化,更新时先清理旧定时器再启动新的。 - 确认重定向函数可用性:如果
clearError是自定义函数,需确保已在组件内正确导入或定义,否则会导致报错中断定时器逻辑,可替换为原生跳转或Vue Router的push方法。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

