• 04.智慧商城——短信验证码倒计时、登录请求、响应拦截器统一处理、请求loading效果


    01. 短信验证倒计时功能

    在这里插入图片描述

    (1) 倒计时基础效果

    1. 准备 data 数据
    data () {
      return {
        totalSecond: 60, // 总秒数
        second: 60, // 倒计时的秒数
        timer: null // 定时器 id
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 给按钮注册点击事件
    <button @click="getCode">
      {{ second === totalSecond ? '获取验证码' : second + `秒后重新发送`}}
    button>
    
    • 1
    • 2
    • 3
    1. 开启倒计时时
    async getCode () {
      // 如果有定时器不存在同时当前计时的时间达到60秒时才能发送获取验证码的请求(当前接口还未写发送请求)
      if (!this.timer && this.second === this.totalSecond) {
        // 开启倒计时
        this.timer = setInterval(() => {
          this.second--
    
          if (this.second < 1) {
            clearInterval(this.timer)
            this.timer = null
            this.second = this.totalSecond
          }
        }, 1000)
    
        // 发送请求,获取验证码
        this.$toast('发送成功,请注意查收')
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    1. 离开页面销毁定时器
    destroyed () {
      clearInterval(this.timer)
    }
    
    • 1
    • 2
    • 3

    (2) 验证码请求校验处理

    1. 输入框 v-model 绑定变量
    data () {
      return {
        mobile: '', // 手机号
        picCode: '' // 图形验证码
      }
    },
        
    <input v-model="mobile" class="inp" maxlength="11" placeholder="请输入手机号码" type="text">
    <input v-model="picCode" class="inp" maxlength="5" placeholder="请输入图形验证码" type="text">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. methods中封装校验方法
    // 校验输入框内容
    validFn () {
      if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
        this.$toast('请输入正确的手机号')
        return false
      }
      if (!/^\w{4}$/.test(this.picCode)) {
        this.$toast('请输入正确的图形验证码')
        return false
      }
      return true
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 请求倒计时前进行校验
    // 获取短信验证码
    async getCode () {
      if (!this.validFn()) {
        return
      }
      ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (3) 封装接口,请求获取验证码

    1. 封装接口 api/login.js
    // 获取短信验证码
    export const getMsgCode = (captchaCode, captchaKey, mobile) => {
      return request.post('/captcha/sendSmsCaptcha', {
        form: {
          captchaCode,
          captchaKey,
          mobile
        }
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 调用接口,添加提示
    // 获取短信验证码
    async getCode () {
      //当验证码和手机号格式正确时才能往下走
      if (!this.validFn()) {
        return
      }
    
      if (!this.timer && this.second === this.totalSecond) {
        // 发送请求,获取验证码
        await getMsgCode(this.picCode, this.picKey, this.mobile)
        this.$toast('发送成功,请注意查收')
        
        // 开启倒计时
        ...
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    02. 封装api接口 - 登录功能

    api/login.js 提供登录 Api 函数

    // 验证码登录
    export const codeLogin = (mobile, smsCode) => {
      return request.post('/passport/login', {
        form: {
          isParty: false,
          mobile,
          partyData: {},
          smsCode
        }
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    login/index.vue 登录功能

    
    
    
    data () {
      return {
        msgCode: '',
      }
    },
    methods: {
      async login () {
        if (!this.validFn()) {
          return
        }
        if (!/^\d{6}$/.test(this.msgCode)) {
          this.$toast('请输入正确的手机验证码')
          return
        }
        await codeLogin(this.mobile, this.msgCode)
        this.$router.push('/')
        this.$toast('登录成功')
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    03. 响应拦截器统一处理错误提示

    响应拦截器是咱们拿到数据的 第一个 “数据流转站”,可以在里面统一处理错误,只要不是 200 默认给提示,抛出错误

    utils/request.js

    import { Toast } from 'vant'
    
    ...
    
    // 添加响应拦截器
    request.interceptors.response.use(function (response) {
      const res = response.data
      if (res.status !== 200) {
        Toast(res.message)
        return Promise.reject(res.message)
      }
      // 对响应数据做点什么
      return res
    }, function (error) {
      // 对响应错误做点什么
      return Promise.reject(error)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    04. 将登录权证信息存入 vuex

    1. 新建 vuex user 模块 store/modules/user.js
    export default {
      namespaced: true,
      state () {
        return {
          userInfo: {
            token: '',
            userId: ''
          },
        }
      },
      mutations: {},
      actions: {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 挂载到 vuex 上
    import Vue from 'vue'
    import Vuex from 'vuex'
    import user from './modules/user'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      modules: {
        user,
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 提供 mutations
    mutations: {
      setUserInfo (state, obj) {
        state.userInfo = obj
      },
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 页面中 commit 调用
    // 登录按钮(校验 & 提交)
    async login () {
      if (!this.validFn()) {
        return
      }
      ...
      const res = await codeLogin(this.mobile, this.msgCode)
      this.$store.commit('user/setUserInfo', res.data)
      this.$router.push('/')
      this.$toast('登录成功')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    05. vuex持久化处理

    1. 新建 utils/storage.js 封装方法
    const INFO_KEY = 'hm_shopping_info'
    
    // 获取个人信息
    export const getInfo = () => {
      const result = localStorage.getItem(INFO_KEY)
      return result ? JSON.parse(result) : {
        token: '',
        userId: ''
      }
    }
    
    // 设置个人信息
    export const setInfo = (info) => {
      localStorage.setItem(INFO_KEY, JSON.stringify(info))
    }
    
    // 移除个人信息
    export const removeInfo = () => {
      localStorage.removeItem(INFO_KEY)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. vuex user 模块持久化处理
    import { getInfo, setInfo } from '@/utils/storage'
    export default {
      namespaced: true,
      state () {
        return {
          userInfo: getInfo()
        }
      },
      mutations: {
        setUserInfo (state, obj) {
          state.userInfo = obj
          setInfo(obj)
        }
      },
      actions: {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    06. 优化:添加请求 loading 效果

    1. 请求时,打开 loading
    // 添加请求拦截器
    request.interceptors.request.use(function (config) {
      // 在发送请求之前做些什么
      Toast.loading({
        message: '请求中...',
        forbidClick: true,  // 禁止背景点击,(节流处理,防止多次无效请求)
        loadingType: 'spinner',  //设置加载图标,不设置会使用默认的小圆圈,这里设置为一个发散的小圆圈
        duration: 0   // 加载图标不会自动消失
      })
      return config
    }, function (error) {
      // 对请求错误做些什么
      return Promise.reject(error)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 响应时,关闭 loading
    // 添加响应拦截器
    import { Toast } from 'vant'
    
    request.interceptors.response.use(function (response) {
      const res = response.data
      if (res.status !== 200) {
        Toast(res.message)
        return Promise.reject(res.message)
      } else {
        // 清除 loading 中的效果
        Toast.clear()
      }
      // 对响应数据做点什么
      return res
    }, function (error) {
      // 对响应错误做点什么
      return Promise.reject(error)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    方法的重载
    用这个方法简直开挂!精密空调轻松拿捏
    idea常用快捷键持续更新
    Android handlerThread并发了解
    【python】Windows 系统 chrome禁止更新
    Git+py+ipynb Usage
    嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②
    盒模型(非要让我凑满五个字标题)
    作为思摩尔应对气候变化紧急事件的一项举措,FEELM加入碳披露项目
    用Unity同时开发【微信小游戏】【安卓】【IOS】游戏#6.2 WebSocket通信
  • 原文地址:https://blog.csdn.net/m0_53951384/article/details/134435084