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:;" rel="external nofollow"  rel="external nofollow" 
    @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:;" rel="external nofollow"  rel="external nofollow"  @click="sendCode" >
     {{ timer == 0 ? "發送驗證碼" : `(${timer})後發送驗證碼` }}
  </a> 
</template>

補充 mobileRule

import type { FieldRule } from 'vant'
 
const mobileRules: FieldRule[] = [
  { required: true, message: '請輸入手機號' },
  { pattern: /^1[3-9]\d{9}$/, message: '手機號格式不正確' }
]
 
const passwordRules: FieldRule[] = [
  { required: true, message: '請輸入密碼' },
  { pattern: /^\w{8,24}$/, message: '密碼需8-24個字符' }
]
 
const codeRules: FieldRule[] = [
  { required: true, message: '請輸入驗證碼' },
  { pattern: /^\d{6}$/, message: '驗證碼為6位數字' }
]
 
export { mobileRules, passwordRules, codeRules }

到此這篇關於vue3發送驗證碼倒計時 (防止連點、封裝復用)的文章就介紹到這瞭,更多相關vue3驗證碼倒計時內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: