查看: 265|回复: 0

Vue3+ElementPlus封装useCountDown倒计时Hoo

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在 Vue3 项目开发中,验证码倒计时、按钮防重复提交等场景非常常见。如果直接把倒计时逻辑写在组件里,会导致多个页面重复维护一套定时器代码,既不优雅也容易出错。利用 Vue3 Composition API 提供的 Hooks 机制,可以把倒计时逻辑抽离成独立函数,配合 ElementPlus 按钮组件即可快速复用。

下面以 ElementPlus 的 el-button 为例,演示如何封装一个通用的 useCountDown Hooks,并实现点击按钮显示倒计时、倒计时结束自动恢复初始状态的效果。

一、编写 useCountDown Hooks

在项目 src/hooks 目录下新建 useCountDown.js。该 Hooks 的核心职责是管理倒计时秒数、倒计时状态和定时器生命周期。
  1. // hooks/useCountDown.js
  2. import { ref, watch } from "vue";
  3. // 默认倒计时时长 60 秒,也可按需传入
  4. export function useCountDown(num = 60) {
  5.   // 倒计时剩余秒数
  6.   const count = ref(num);
  7.   // 是否处于倒计时中
  8.   const isDown = ref(false);
  9.   // 定时器 id
  10.   let timerId = null;
  11.   // 开始倒计时
  12.   const start = () => {
  13.     // 防止重复点击导致多个定时器叠加
  14.     if (isDown.value) return;
  15.     isDown.value = true;
  16.     timerId = setInterval(() => {
  17.       count.value--;
  18.     }, 1000);
  19.   };
  20.   // 监听 count,归零时清除定时器并重置状态
  21.   watch(count, (newCount) => {
  22.     if (newCount <= 0) {
  23.       clearInterval(timerId);
  24.       count.value = num;      // 重置为初始秒数
  25.       isDown.value = false;   // 标记倒计时结束
  26.     }
  27.   });
  28.   return {
  29.     count,
  30.     isDown,
  31.     start
  32.   };
  33. }
复制代码

这里有一个细节值得注意:start 函数内部首先判断 isDown.value 是否为 true,如果当前已经在倒计时中,则直接返回。这样能有效防止用户连点时创建多个 setInterval,避免倒计时速度异常。

watch 监听 count 的作用是自动完成结束后的清理与状态复位。当 count 减到 0 时,清除定时器、把 count 重置为最初传入的 num,并把 isDown 置回 false。这样组件无需额外关心重置逻辑,下一次点击 start 又能从完整时长开始倒计时。

二、在 ElementPlus 页面中使用

在业务组件的模板中,使用 el-button 绑定点击事件,并利用 isDown 控制按钮显示文本。倒计时中显示“正在倒计时(剩余秒数)”,否则显示“开始倒计时”。
  1. <!-- xxx/index.vue -->
  2. <template>
  3.   <el-button type="primary" @click="countDownFn">
  4.     <span v-if="isDown">正在倒计时({{ count }})</span>
  5.     <span v-else>开始倒计时</span>
  6.   </el-button>
  7. </template>
  8. <script setup>
  9. // 导入 Hooks 函数
  10. import { useCountDown } from "@/hooks/useCountDown";
  11. // 传入 10 秒,也可以改为 60 秒满足验证码场景
  12. const { count, isDown, start } = useCountDown(10);
  13. // 点击按钮时触发 start
  14. const countDownFn = () => {
  15.   start();
  16. };
  17. </script>
  18. <style lang="scss" scoped>
  19. /* 按需编写样式 */
  20. </style>
复制代码

如果实际场景是“发送验证码”按钮,只需要把 useCountDown(10) 改为 useCountDown(60),并把 el-button 的 :disabled 属性绑定为 isDown,即可同时获得 60 秒倒计时与禁用状态:
  1. <el-button type="primary" :disabled="isDown" @click="countDownFn">
  2.   {{ isDown ? `重新发送(${count}s)` : "获取验证码" }}
  3. </el-button>
复制代码

三、扩展思路

由于 useCountDown 返回的是响应式对象,其他组件也可以直接调用。若要实现“发送成功后才开始倒计时”,可以在发送接口成功回调里调用 start(),而不是绑定在按钮点击时立刻启动。这样能避免用户输错号码、接口报错后仍盲目进入倒计时状态。

另外,若要在倒计时结束后执行额外操作(如跳转页面),可以在 watch 回调中判断 newCount <= 0 后,再通过回调参数或自定义事件通知组件。不过示例代码没有包含这部分逻辑,实际开发时可以根据项目需求灵活扩展。

这套 Hooks + ElementPlus 的组合方案,代码量少、逻辑清晰,适合用于验证码倒计时、营销活动限时按钮、短信重发等常见交互场景。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-6 15:31 , Processed in 0.021678 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部