验证码 - 倒计时 v3+ts+pinia

643 阅读2分钟

验证码 - 倒计时 这个功能的实现,我这边归纳总结了三点

  1. 定时器
  2. 使用useIntervalFn 改写代码
  3. 封装倒计时功能

1.定时器

 //1.定义初始值 并导出
  
  import { ref } from 'vue';
  const counter = ref(0)
    
  // 2.在发送验证码 那里绑定个点击事件
  
  <span class='code' @click='send'>发送验证码</span>
  
  后改为
  <span class="code" @click="send">{{ counter === 0 ? '发送验证码' : counter+'秒之后再试' }}</span>
  
  const send = async() => {
    //校验手机号
    const res = await mobileValidate()
    if(!res.valid) { //没有通过校验
      // dom获取焦点
      // ? 是 js的自带的可选链
      refMobile.value?.focus()
      return
    }
    //调用后端接口,向手机号发送验证码
    try{
      await user.sendMobileMsg(mobile.value)
      
      //验证码发成功
      //开启倒计时,有一个数在按钮上显示,越来越小
      counter.value = 10
      const timer = setInterval(() =>{
        if(counter.value === 0){
          //清除定时器
          clearInterval(timer)
        } else {
           counter.value--
        }
      },1000)
    }catch(err) {
    
    }
  }

注解上面代码

refMobile 是在input请输入手机号 上面 设置 ref=refMobile

mobileValidate 是 结构赋值重命名

const { value: mobile, errorMessage:mobileError, validate: mobileValidate } = useField<string>('mobile')

2.使用useIntervalFn 改写代码

第一步下包 并引入 import {useIntervalFn} from '@vueuse/core'

//1.初始值
const counter = ref(0)
const { pause,resume } = useIntervalFn(() => {
  if(counter.value === 0) {
      pause() //暂停
  } else{
      counter.value--
  }
},1000,{immediate:false})

const send = async() => {
  if(counter.value > 0) return //若不加这行代码,点击时就可以暂停,
  //校验手机号
  const res = await mobileValidate()
  if(!res.valid) {
      refMobile.value?.focus()
      return
  }
  try{
    await user.sendMobileMsg(mobile.value)
    //开始倒计时
    counter.value = 10
    resume() //开始
  }catch(err){
  
  }
}

注解

pause,resume是useIntervalFn自带的方法
语法
const { pause: 暂停, resume: 开始 } = useIntervalFn(() => {
  // 回调
}, 间隔时长, {immediate: 是否立即执行})

3.封装倒计时功能

在src -> utils -> hooks.ts 1.导入 import {useIntersectionObserver,useIntervalFn} from '@vueuse/core' import {ref} from 'vue' 2.创建函数并导出

export function useCount() {
  const counter = ref(0)
  const {pause,resume} = useIntervalFn(() =>{
     if(counter.value === 0){
         pause()
     } else {
        counter.value--
     }
  },1000,{immediate:false})
  const start = (num:number) => {
     counter.value = num
     resume()
  }
  return{counter,start}
}

3.在src -> views -----.vue文件 import {useCount} from '@/utils/hooks' 就直接写

const {counter,start} = useCount()
const send = async() => {
  if(counter.value > 0) return //若不加这行代码,点击时就可以暂停,
  //校验手机号
  const res = await mobileValidate()
  if(!res.valid) {
      refMobile.value?.focus()
      return
  }
  try{
    await user.sendMobileMsg(mobile.value)
    //开始倒计时
   start(10)
  }catch(err){
  
  }
}