vue3.0实现炫酷的随机验证码功能

先上图

接下来楼一眼实现代码

这里说明一下,我用到了vue3.0,vant3.0以及阿里图标,vant 很人性化针对vue3.0新出了个vant3.0版本,阿里则是适配vue3.0的。我们将verify验证码进行了封装,内部用进行了hook以及工具的封装。

登录页代码 login.vue

<template>
  <div class="login">
    <span class="iconfont icongouwuche"></span>
    <van-form @submit="onSubmit">
      <van-field
        v-model="username"
        name="username"
        label="用户名"
        placeholder="用户名"
        :rules="[{ required: true, message: '请填写用户名' }]"
      />
      <van-field
        v-model="password"
        type="password"
        name="password"
        label="密码"
        placeholder="密码"
        :rules="[{ required: true, message: '请填写密码' }]"
      />
      <van-field
        center
        clearable
        label="验证码"
        placeholder="输入验证码"
        v-model="verify"
      >
      </van-field>
      <ImgVerify ref="verifyRef" />
      <div style="margin: 16px">
        <van-button round block color="#1baeae" native-type="submit">
          登录</van-button
        >
      </div>
    </van-form>
  </div>
</template>

<script>
import { reactive, ref, toRefs } from "vue";
import ImgVerify from "@/components/ImgVerify";
export default {
  components: { ImgVerify },
  setup(props, con) {
    const verifyRef = ref(null);

    const state = reactive({
      username: "",
      password: "",
      verify: "",
    });
    const onSubmit = (values) => {
      if (state.verify.toLowerCase() == verifyRef.value.imgCode.toLowerCase()) {
        //   提交时判断是否是正确验证码
        alert("输入正确");
        TODO;
        //
      }
    };

    return {
      ...toRefs(state),
      onSubmit,
      verifyRef,
    };
  },
};
</script>

<style lang='scss' scoped>
.login {
  /* background: #eee; */
}
div {
  font-size: 14px;
  .icongouwuche {
    padding-top: 40px;
    font-size: 120px;
  }
}
</style>

验证码组件 ImgVerify.vue

这里只是简单地获取以及排版,正正的逻辑放到了hook中

<template>
  <div>
    <canvas
      ref="verify"
      :width="width"
      :height="height"
      @click="handleDraw"
    ></canvas>
  </div>
</template>

<script>
import {ref } from "vue";
import {setVerify} from '../hooks/Verify'
export default {
  setup(props, con) {
    const verify = ref(null);
    return{
        ...setVerify(verify)
    }
  },
};
</script>

<style lang='scss' scoped>
</style>

我们先看一下封装好的tool工具函数。

Tool.js

//随机数
export function randomNum(min, max) {
    return parseInt(Math.random() * (max - min + 1) + min);
};
//随机颜色
export function randomColor(min, max) {
    const r = randomNum(min, max);
    const g = randomNum(min, max);
    const b = randomNum(min, max);
    return `rgb(${r},${g},${b})`;
};

接下来重头戏实现验证码

verify.js

import { onMounted, toRefs, reactive } from "vue";
import { randomColor, randomNum } from '../utils/Tools'
export function setVerify(verify) {
    const state = reactive({
        pool: "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",   // 随机字符串
        width: 120,                                     //展示区域宽度
        height: 40,                                     //展示区域高度
        imgCode: "",                                    //保存页面的内容(用来判断输入验证是否满足改code)
    });
    // 1、初始展示
    onMounted(() => {
        draw();
        state.imgCode = draw();
    });
    // 2、点击图片重新绘制
    const handleDraw = () => {
        draw();
        state.imgCode = draw();
    };

    // 3、绘制随机内容
    const draw = () => {
        /*
         *   一、填充颜色
         * 1、生成画布
         * 2、填充颜色与位置
         * 3、填充位置
         */
        const ctx = verify.value.getContext("2d");
        ctx.fillStyle = randomColor(180, 230);
        ctx.fillRect(0, 0, state.width, state.height);

        /*
         *    二、生成4个随机数
         *  1、七扭八歪
         *  2、随机大小
         * 3、画吧柳梢,各种色儿
         */
        let imgCode = "";
        for (let i = 0; i < 4; i++) {
            const text = state.pool[randomNum(0, state.pool.length - 1)];

            const fontSize = randomNum(18, 40);
            const deg = randomNum(-30, 30);
            /*
             *  绘制文字并让四个文字在不同的位置显示的思路 :
             * 1、定义字体
             * 2、定义对齐方式
             * 3、填充不同的颜色
             * 4、保存当前的状态(以防止以上的状态受影响)
             * 5、平移translate()
             * 6、旋转 rotate()
             * 7、填充文字
             * 8、restore出栈
             * */
            ctx.font = fontSize + "px Simhei";
            ctx.textBaseline = "top";
            ctx.fillStyle = randomColor(80, 150);

ctx.save(); ctx.translate(30 * i + 15, 15); ctx.rotate((deg * Math.PI) / 180); ctx.fillText(text, -15 + 5, -15); ctx.restore(); imgCode += text; } /* * 三、随机产生5条干扰线,干扰线的颜色要浅一点 */ for (let i = 0; i < 5; i++) { ctx.beginPath(); ctx.moveTo(randomNum(0, state.width), randomNum(0, state.height)); ctx.lineTo(randomNum(0, state.width), randomNum(0, state.height)); ctx.strokeStyle = randomColor(180, 230); ctx.closePath(); ctx.stroke(); } /* * 四、随机产生40个干扰的小点 */ for (let i = 0; i < 40; i++) { ctx.beginPath(); ctx.arc( randomNum(0, state.width), randomNum(0, state.height), 1, 0, 2 * Math.PI ); ctx.closePath(); ctx.fillStyle = randomColor(150, 200); ctx.fill(); } return imgCode; }; return { ...toRefs(state), handleDraw, verify, }; }

一个vscode快熟生成vue3代码片段的方法

1、选择      文件---》首选项---》代码片段---》

2、新建json

 

3、配置json

 "Print to console": {
        "prefix": "vue3",
        "body": [
            "<template>",
            "<div>",
            "",
            "</div>",
            "</template>",
            "",
            "<script>",
            "export default {",
            "   components: {},",
         
            "   setup(props,con){}",
            "}",
            "</script>",
            "",
            "<style lang='scss' scoped>",
            "",
            "</style>",
            "$2"
        ],
        "description": "Vue3模板"
    }

 

posted @ 2021-05-27 13:31  久宇诗  阅读(1539)  评论(0编辑  收藏  举报