Vue3+ElementPlus封装useCountDown倒计时Hoo
在 Vue3 项目开发中,验证码倒计时、按钮防重复提交等场景非常常见。如果直接把倒计时逻辑写在组件里,会导致多个页面重复维护一套定时器代码,既不优雅也容易出错。利用 Vue3 Composition API 提供的 Hooks 机制,可以把倒计时逻辑抽离成独立函数,配合 ElementPlus 按钮组件即可快速复用。下面以 ElementPlus 的 el-button 为例,演示如何封装一个通用的 useCountDown Hooks,并实现点击按钮显示倒计时、倒计时结束自动恢复初始状态的效果。
一、编写 useCountDown Hooks
在项目 src/hooks 目录下新建 useCountDown.js。该 Hooks 的核心职责是管理倒计时秒数、倒计时状态和定时器生命周期。
// hooks/useCountDown.js
import { ref, watch } from "vue";
// 默认倒计时时长 60 秒,也可按需传入
export function useCountDown(num = 60) {
// 倒计时剩余秒数
const count = ref(num);
// 是否处于倒计时中
const isDown = ref(false);
// 定时器 id
let timerId = null;
// 开始倒计时
const start = () => {
// 防止重复点击导致多个定时器叠加
if (isDown.value) return;
isDown.value = true;
timerId = setInterval(() => {
count.value--;
}, 1000);
};
// 监听 count,归零时清除定时器并重置状态
watch(count, (newCount) => {
if (newCount <= 0) {
clearInterval(timerId);
count.value = num; // 重置为初始秒数
isDown.value = false; // 标记倒计时结束
}
});
return {
count,
isDown,
start
};
}
这里有一个细节值得注意:start 函数内部首先判断 isDown.value 是否为 true,如果当前已经在倒计时中,则直接返回。这样能有效防止用户连点时创建多个 setInterval,避免倒计时速度异常。
watch 监听 count 的作用是自动完成结束后的清理与状态复位。当 count 减到 0 时,清除定时器、把 count 重置为最初传入的 num,并把 isDown 置回 false。这样组件无需额外关心重置逻辑,下一次点击 start 又能从完整时长开始倒计时。
二、在 ElementPlus 页面中使用
在业务组件的模板中,使用 el-button 绑定点击事件,并利用 isDown 控制按钮显示文本。倒计时中显示“正在倒计时(剩余秒数)”,否则显示“开始倒计时”。
<!-- xxx/index.vue -->
<template>
<el-button type="primary" @click="countDownFn">
<span v-if="isDown">正在倒计时({{ count }})</span>
<span v-else>开始倒计时</span>
</el-button>
</template>
<script setup>
// 导入 Hooks 函数
import { useCountDown } from "@/hooks/useCountDown";
// 传入 10 秒,也可以改为 60 秒满足验证码场景
const { count, isDown, start } = useCountDown(10);
// 点击按钮时触发 start
const countDownFn = () => {
start();
};
</script>
<style lang="scss" scoped>
/* 按需编写样式 */
</style>
如果实际场景是“发送验证码”按钮,只需要把 useCountDown(10) 改为 useCountDown(60),并把 el-button 的 :disabled 属性绑定为 isDown,即可同时获得 60 秒倒计时与禁用状态:
<el-button type="primary" :disabled="isDown" @click="countDownFn">
{{ isDown ? `重新发送(${count}s)` : "获取验证码" }}
</el-button>
三、扩展思路
由于 useCountDown 返回的是响应式对象,其他组件也可以直接调用。若要实现“发送成功后才开始倒计时”,可以在发送接口成功回调里调用 start(),而不是绑定在按钮点击时立刻启动。这样能避免用户输错号码、接口报错后仍盲目进入倒计时状态。
另外,若要在倒计时结束后执行额外操作(如跳转页面),可以在 watch 回调中判断 newCount <= 0 后,再通过回调参数或自定义事件通知组件。不过示例代码没有包含这部分逻辑,实际开发时可以根据项目需求灵活扩展。
这套 Hooks + ElementPlus 的组合方案,代码量少、逻辑清晰,适合用于验证码倒计时、营销活动限时按钮、短信重发等常见交互场景。
Re: Vue3+ElementPlus封装useCountDown倒计时Hoo
这个封装思路很清晰,把倒计时逻辑从组件里抽出来确实能减少很多重复代码。特别是用 `isDown` 做防重复点击的判断,还有 `watch` 里自动重置状态,细节处理得很到位,直接拿来用在验证码按钮上很顺手。 补充一个小建议:如果组件在倒计时过程中被销毁了(比如路由切换),`setInterval` 可能还会继续跑,建议在 Hooks 里加上 `onUnmounted` 清理逻辑,或者使用 `clearInterval` 兜底一下,避免内存泄漏或潜在的状态更新告警。 另外,如果遇到“接口成功后开始倒计时”的场景,目前返回的 `start` 调用方式也完全支持,灵活性挺好。感谢分享这套实用方案。Re: Vue3+ElementPlus封装useCountDown倒计时Hoo
这个封装很实用,正好解决了多个页面重复写倒计时逻辑的痛点。把 `isDown` 作为状态暴露出来,配合 Element Plus 的按钮禁用和文案切换非常自然。特别赞同用 `watch` 统一处理归零重置的做法,这样组件侧就不用关心定时器清理了。 一个小建议:如果后续有倒计时结束后需要跳出倒计时状态但不重置 `count` 的场景,可能当前自动重置的逻辑会有点局限。不过就验证码和防重复点击这类常见需求来说,这个 Hooks 已经足够清晰高效了。学习了。Re: Vue3+ElementPlus封装useCountDown倒计时Hoo
这个封装思路很清晰,把倒计时逻辑从组件里抽出来确实能减少重复代码。用 `ref` 管理状态、通过 `watch` 自动清理定时器,处理得挺干净。 有个小细节想和你确认下:`watch` 里当 `newCount
页:
[1]