• vue3发送验证码倒计时 (防止连点、封装复用)


    一、实现思路

    倒计时 流程图

    二、实现一个简单的验证码倒计时

    1. //倒计时初始变量
    2. const codeNum = ref(60);
    3. // 定时器id
    4. let clearId: number;
    5. // 发送验证码
    6. const sendCode = async () => {
    7. // 防止下次点击 如果倒计时的时间不是60 就不执行下面逻辑
    8. if (codeNum.value != 60) return;
    9. // 掉接口
    10. const res = await getCode(mobile.value, "login");
    11. // 把定时器赋值给 变量clearId 目的:清除定时器
    12. clearId= setInterval(() => {
    13. // 每次 时间1s -1
    14. codeNum.value--;
    15. // 时间=0时 清除定时器
    16. if (codeNum.value == 0) {
    17. clearInterval(clearId);
    18. // 还原 倒计时60s
    19. codeNum.value = 60;
    20. }
    21. }, 1000);
    22. };

    当然 这只是没有做过优化的一个发送验证码,如果要考虑点击连续点击或者离开页面时销毁定时器 还要加一些功能

    三、优化 

    (1)第一种方案,定义一个变量来控制 如果之前没有点击 再次点击不再执行

    1. <template>
    2. <a
    3. href="javascript:;"
    4. @click="sendCode"
    5. >{{ codeNum == 60 ? "发送验证码" : `(${codeNum})发送验证码` }}a>
    6. template>

    (2)第二种方案. 让倒计时初始值为0 调用函数时在赋值为60 下次值大于0时同样不再执行,实现思路和第一种相似

    1. const codeNum = ref(0);
    2. const sendCode = async () => {
    3. if (codeNum.value > 0) return;
    4. isClickSend.value = true;
    5. const res = await getCode(mobile.value, "login");
    6. codeNum.value = 60
    7. if(clearId) clearInterval(clearId)
    8. clearId = setInterval(() => {
    9. codeNum.value--;
    10. if (codeNum.value == 0) {
    11. clearInterval(clearId);
    12. }
    13. }, 1000);
    14. };

    其中没有对手机号进行校验 若需要则自己可以写校验规则,也可以参考当前使用的其他组件库使用 

    离开页面销毁定时器

    1. onMounted(() => {
    2. clearInterval(clearId)
    3. })

    四、逻辑封装

    为什么要封装 验证码倒计时功能?

    1. 为了下次再次使用时 直接copy代码达到复用

    2. 在日常开发中可能 有很多场景都需要发送验证码 只是 接口一样 只是参数的type值不一样 例如 登录需要传login  注册需要传register 到时候只需要调用更换参数即可

    新建composable/index.ts 准备放公共方法

    1. // 引用 发送的验证码类型
    2. import type { CodeType } from '@/type/user'
    3. // 引入接口
    4. import { getCode } from "@/api/login";
    5. import type { Ref } from 'vue'
    6. // 引入vant form类型 用来初始化form类型 可参考vant 若没有使用 则删除
    7. import type { FormProps, FormInstance } from 'vant';
    8. // 封装方法 只需要传入手机号、 type类型
    9. export const useSendCode = (mobile: Ref, type: CodeType) => {
    10. // 定义定时器初始值为0
    11. const timer = ref(0)
    12. // 定义form变量 如果用了vant 记得要给vanForm 绑定ref
    13. const form = ref<FormInstance | null>() ;
    14. // 定义定时器id 为了清除定时器
    15. let timerId: number
    16. // 之后页面调用send方法来使用
    17. const send = async () => {
    18. // 第二次点击 大于0时 直接 return
    19. if (timer.value > 0) return
    20. // 校验 mobile字段 要和 van-field 中的name保持一直 否则校验失败 如果校验失败则不走下面代码 注意await
    21. await form.value?.validate('mobile')
    22. // 校验通过调用接口
    23. await getCode(mobile.value, type)
    24. // 赋值倒计时 可修改成自己需要的时间
    25. timer.value = 10
    26. // 如果之前id存在可清除
    27. if (timerId) clearInterval(timerId)
    28. // 赋值定时器id
    29. timerId = setInterval(() => {
    30. // 时间-1
    31. timer.value--
    32. // 倒计时结束 清除定时器
    33. if (timer.value == 0) clearInterval(timerId)
    34. }, 1000)
    35. }
    36. //
    37. onMounted(() => {
    38. clearInterval(timerId)
    39. })
    40. return { timer, send, form }
    41. }

     由于代码中使用了插件 没有引入ref onMounted  需要可自行引入

    页面中使用

    1. <template>
    2. <van-form ref="form" @submit="pwdLogin">
    3. <van-field
    4. v-model="mobile"
    5. name="mobile"
    6. maxlength="11"
    7. placeholder="请输入手机号"
    8. :rules="mobileRule"
    9. />
    10. van-form>
    11. ...
    12. <a href="javascript:;" @click="sendCode" >
    13. {{ timer == 0 ? "发送验证码" : `(${timer})后发送验证码` }}
    14. a>
    15. template>

    补充 mobileRule

    1. import type { FieldRule } from 'vant'
    2. const mobileRules: FieldRule[] = [
    3. { required: true, message: '请输入手机号' },
    4. { pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确' }
    5. ]
    6. const passwordRules: FieldRule[] = [
    7. { required: true, message: '请输入密码' },
    8. { pattern: /^\w{8,24}$/, message: '密码需8-24个字符' }
    9. ]
    10. const codeRules: FieldRule[] = [
    11. { required: true, message: '请输入验证码' },
    12. { pattern: /^\d{6}$/, message: '验证码为6位数字' }
    13. ]
    14. export { mobileRules, passwordRules, codeRules }

     

  • 相关阅读:
    正则表达式转换为相应的文字小工具
    全波形反演的深度学习方法: 第二章 正演 (草稿)
    若依架构下的质检项目的记录
    Logrus日志
    leetcode第145题python版二叉树后序遍历迭代法
    免费开源软件,医院能用吗?
    一起走过的那些日子-2022年七夕
    TSINGSEE青犀AI视频分析/边缘计算/AI算法·人脸识别功能——多场景高效运用
    Arduino 拓展班DMP280的代码问题
    基于Chirp窄带扩频技术的无线混合组网应用,以多角色智能计量插座作为Chirp广域基站,构建边缘计算混合无线网络
  • 原文地址:https://blog.csdn.net/m0_46846526/article/details/128093517