vue3发送验证码倒计时 (防止连点封装复用)
Posted 奥特曼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue3发送验证码倒计时 (防止连点封装复用)相关的知识,希望对你有一定的参考价值。
一、实现思路
二、实现一个简单的验证码倒计时
//倒计时初始变量
const codeNum = ref(60);
// 定时器id
let clearId: number;
// 发送验证码
const sendCode = async () =>
// 防止下次点击 如果倒计时的时间不是60 就不执行下面逻辑
if (codeNum.value != 60) return;
// 掉接口
const res = await getCode(mobile.value, "login");
// 把定时器赋值给 变量clearId 目的:清除定时器
clearId= setInterval(() =>
// 每次 时间1s -1
codeNum.value--;
// 时间=0时 清除定时器
if (codeNum.value == 0)
clearInterval(clearId);
// 还原 倒计时60s
codeNum.value = 60;
, 1000);
;
当然 这只是没有做过优化的一个发送验证码,如果要考虑点击连续点击或者离开页面时销毁定时器 还要加一些功能
三、优化
(1)第一种方案,定义一个变量来控制 如果之前没有点击 再次点击不再执行
<script lang="ts" setup>
// 接口
import getCode from "@/api/login";
// 定时器id
let clearId:number;
// 倒计时时间
const codeNum = ref(60);
// 手机号
const mobile = ref("13230000001");
// 是否发送了验证码 防止连点
+ const isClickSend = ref(false);
// 发送验证码
const sendCode = async () =>
+ if (isClickSend.value || codeNum.value != 60) return;
isClickSend.value = true;
const res = await getCode(mobile.value, "login");
clearId.value = setInterval(() =>
codeNum.value--;
if (codeNum.value == 0)
clearInterval(clearId.value);
codeNum.value = 60;
+ isClickSend.value = false;
, 1000);
console.log("sendCode", res);
;
</script>
<template>
<a
href="javascript:;"
@click="sendCode"
> codeNum == 60 ? "发送验证码" : `($codeNum)发送验证码` </a>
</template>
(2)第二种方案. 让倒计时初始值为0 调用函数时在赋值为60 下次值大于0时同样不再执行,实现思路和第一种相似
const codeNum = ref(0);
const sendCode = async () =>
if (codeNum.value > 0) return;
isClickSend.value = true;
const res = await getCode(mobile.value, "login");
codeNum.value = 60
if(clearId) clearInterval(clearId)
clearId = setInterval(() =>
codeNum.value--;
if (codeNum.value == 0)
clearInterval(clearId);
, 1000);
;
其中没有对手机号进行校验 若需要则自己可以写校验规则,也可以参考当前使用的其他组件库使用
离开页面销毁定时器
onMounted(() =>
clearInterval(clearId)
)
四、逻辑封装
为什么要封装 验证码倒计时功能?
1. 为了下次再次使用时 直接copy代码达到复用
2. 在日常开发中可能 有很多场景都需要发送验证码 只是 接口一样 只是参数的type值不一样 例如 登录需要传login 注册需要传register 到时候只需要调用更换参数即可
新建composable/index.ts 准备放公共方法
// 引用 发送的验证码类型
import type CodeType from '@/type/user'
// 引入接口
import getCode from "@/api/login";
import type Ref from 'vue'
// 引入vant form类型 用来初始化form类型 可参考vant 若没有使用 则删除
import type FormProps, FormInstance from 'vant';
// 封装方法 只需要传入手机号、 type类型
export const useSendCode = (mobile: Ref<string>, type: CodeType) =>
// 定义定时器初始值为0
const timer = ref(0)
// 定义form变量 如果用了vant 记得要给vanForm 绑定ref
const form = ref<FormInstance | null>() ;
// 定义定时器id 为了清除定时器
let timerId: number
// 之后页面调用send方法来使用
const send = async () =>
// 第二次点击 大于0时 直接 return
if (timer.value > 0) return
// 校验 mobile字段 要和 van-field 中的name保持一直 否则校验失败 如果校验失败则不走下面代码 注意await
await form.value?.validate('mobile')
// 校验通过调用接口
await getCode(mobile.value, type)
// 赋值倒计时 可修改成自己需要的时间
timer.value = 10
// 如果之前id存在可清除
if (timerId) clearInterval(timerId)
// 赋值定时器id
timerId = setInterval(() =>
// 时间-1
timer.value--
// 倒计时结束 清除定时器
if (timer.value == 0) clearInterval(timerId)
, 1000)
//
onMounted(() =>
clearInterval(timerId)
)
return timer, send, form
由于代码中使用了插件 没有引入ref onMounted 需要可自行引入
页面中使用
<script lang="ts" setup>
import mobileRule from "@/utils/rule";
import useSendCode from "@/composable";
const send, timer, form = useSendCode(mobile, "login");
</script>
<template>
<van-form ref="form" @submit="pwdLogin">
<van-field
v-model="mobile"
name="mobile"
maxlength="11"
placeholder="请输入手机号"
:rules="mobileRule"
/>
</van-form>
...
<a href="javascript:;" @click="sendCode" >
timer == 0 ? "发送验证码" : `($timer)后发送验证码`
</a>
</template>
补充 mobileRule
import type FieldRule from 'vant'
const mobileRules: FieldRule[] = [
required: true, message: '请输入手机号' ,
pattern: /^1[3-9]\\d9$/, message: '手机号格式不正确'
]
const passwordRules: FieldRule[] = [
required: true, message: '请输入密码' ,
pattern: /^\\w8,24$/, message: '密码需8-24个字符'
]
const codeRules: FieldRule[] = [
required: true, message: '请输入验证码' ,
pattern: /^\\d6$/, message: '验证码为6位数字'
]
export mobileRules, passwordRules, codeRules
以上是关于vue3发送验证码倒计时 (防止连点封装复用)的主要内容,如果未能解决你的问题,请参考以下文章
react native中的聊天气泡以及timer封装成的发送验证码倒计时