vue中用户登录之验证码的实现

168 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

效果展示

图片.png

1.在component中新增公共组件

在components目录下新建文件Identify.vue

<!-- Identify.vue-->
<template>
 <div class="s-canvas">
  <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
 </div>
</template>
<script>
export default{
 name: 'SIdentify',
 props: {
  identifyCode: { // 默认注册码
   type: String,
   default: '1234'
  },
  fontSizeMin: { // 字体最小值
   type: Number,
   default: 25
  },
  fontSizeMax: { // 字体最大值
   type: Number,
   default: 35
  },
  backgroundColorMin: { // 验证码图片背景色最小值
   type: Number,
   default: 200
  },
  backgroundColorMax: { // 验证码图片背景色最大值
   type: Number,
   default: 220
  },
  dotColorMin: { // 背景干扰点最小值
   type: Number,
   default: 60
  },
  dotColorMax: { // 背景干扰点最大值
   type: Number,
   default: 120
  },
  contentWidth: { // 容器宽度
   type: Number,
   default: 90
  },
  contentHeight: { // 容器高度
   type: Number,
   default: 35
  }
 },
 methods: {
  // 生成一个随机数
  randomNum (min, max) {
   return Math.floor(Math.random() * (max - min) + min)
  },
 
  // 生成一个随机的颜色
  randomColor (min, max) {
   let r = this.randomNum(min, max)
   let g = this.randomNum(min, max)
   let b = this.randomNum(min, max)
   return 'rgb(' + r + ',' + g + ',' + b + ')'
  },
 
  drawPic () {
   let canvas = document.getElementById('s-canvas')
   let ctx = canvas.getContext('2d')
   ctx.textBaseline = 'bottom'
   // 绘制背景
   ctx.fillStyle = '#e6ecfd'
   ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
   // 绘制文字
   for (let i = 0; i < this.identifyCode.length; i++) {
    this.drawText(ctx, this.identifyCode[i], i)
   }
   this.drawLine(ctx)
   this.drawDot(ctx)
  },
 
  drawText (ctx, txt, i) {
   ctx.fillStyle = this.randomColor(50, 160) // 随机生成字体颜色
   ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei' // 随机生成字体大小
   let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
   let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
   var deg = this.randomNum(-30, 30)
   // 修改坐标原点和旋转角度
   ctx.translate(x, y)
   ctx.rotate(deg * Math.PI / 180)
   ctx.fillText(txt, 0, 0)
   // 恢复坐标原点和旋转角度
   ctx.rotate(-deg * Math.PI / 180)
   ctx.translate(-x, -y)
  },
 
  drawLine (ctx) {
   // 绘制干扰线
   for (let i = 0; i < 4; i++) {
    ctx.strokeStyle = this.randomColor(100, 200)
    ctx.beginPath()
    ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
    ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
    ctx.stroke()
   }
  },
 
  drawDot (ctx) {
   // 绘制干扰点
   for (let i = 0; i < 30; i++) {
    ctx.fillStyle = this.randomColor(0, 255)
    ctx.beginPath()
    ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)
    ctx.fill()
   }
  }
 },
 watch: {
  identifyCode () {
   this.drawPic()
  }
 },
 mounted () {
  this.drawPic()
 }
}
</script>

2.在页面中导入组件

在views目录下新建一个vue

<div class="code">
	<img :src="codeImg" class="login-icon">
		<input type="text" v-model="ruleForm.code" id="code" placeholder="验证码">
		<div class="code_img">
			<div class="login-code" @click="refreshCode">
		<Identify :identifyCode="identifyCode"></Identify>
			</div>
		</div>
</div>
import Identify from "@/components/Identify";
components: {Identify}
data() {
			return {
				//验证码图标
				codeImg: require('@/assets/login_images/code.png'),
				ruleForm: {
					code: ''
				},
				//用于显示什么的验证码,可以添加字母
				identifyCodes: '1234567890',
				identifyCode: '',
			}
		},
mounted() {
			// 初始化验证码
			this.identifyCode = ''
			this.makeCode(this.identifyCodes, 4)
		},
methods: {
//刷新验证码
refreshCode() {
		this.ruleForm.code = ''
		this.identifyCode = ''
		this.makeCode(this.identifyCodes, 4)
	},
//生成验证码
makeCode(o, l) {
	for (let i = 0; i < l; i++) {
	this.identifyCode += this.identifyCodes[this.randomNum(0, this.identifyCodes.length)]
		}
},
//生成随机数
randomNum(min, max) {
	return Math.floor(Math.random() * (max - min) + min)
	},
}

完整代码显示

<template>

    <div class="login">

        <div class="login_main">

            <div class="main_right">

                <div class="right_title">用户登录</div>

                <a-form

                    id="form1"

                    name="form1"

                    :model="ruleForm"

                    style="padding: 20px"

                    autocomplete="off"

                >

                    <div class="login-box">

                        <img :src="userImg" class="login-icon" />

                        <input

                            type="text"

                            v-model="ruleForm.username"

                            placeholder="账号"

                        />

                    </div>

                    <div>

                        <img :src="pwdImg" class="login-icon" />

                        <input

                            type="password"

                            v-model="ruleForm.password"

                            placeholder="密码"

                        />

                    </div>

                    <div class="code">

                        <img :src="codeImg" class="login-icon" />

                        <input

                            type="text"

                            v-model="ruleForm.code"

                            id="code"

                            placeholder="验证码"

                        />

                        <div class="code_img">

                            <div class="login-code" @click="refreshCode">

                                <Identify

                                    :identifyCode="identifyCode"

                                ></Identify>

                            </div>

                        </div>

                    </div>

                    <div class="yes_login">

                        <a-button

                            type="primary"

                            class="login-btn"

                            @click="Login"

                            >登录</a-button

                        >

                    </div>

                </a-form>

            </div>

        </div>

    </div>

</template>


<script>

import Identify from "@/components/Identify"

export default {

    components: { Identify },

    props: {},

    data() {

        return {

            //用户图标

            userImg: require("@/assets/login_images/login.png"),

            //密码图标

            pwdImg: require("@/assets/login_images/pwd.png"),

            //验证码图标

            codeImg: require("@/assets/login_images/code.png"),

            ruleForm: {

                password: "",

                username: "",

                code: ""

            },

            rules: {

                username: [

                    {

                        required: true,

                        message: "请输入账号",

                        trigger: "blur"

                    }

                ],

                password: [

                    {

                        required: true,

                        message: "请输入密码",

                        trigger: "blur"

                    }

                ],

                code: [

                    {

                        required: true,

                        message: "请输入验证码",

                        trigger: "blur"

                    }

                ]

            },

            //用于显示什么的验证码,可以添加字母

            identifyCodes: "1234567890",

            identifyCode: ""

        }

    },

    computed: {},

    watch: {},

    created() {},

    mounted() {

        // 初始化验证码

        this.identifyCode = ""

        this.makeCode(this.identifyCodes, 4)

    },

    methods: {

        Login() {

            console.log("登录")

        },

        //刷新验证码

        refreshCode() {

            this.ruleForm.code = ""

            this.identifyCode = ""

            this.makeCode(this.identifyCodes, 4)

        },

        //生成验证码

        makeCode(o, l) {

            for (let i = 0; i < l; i++) {

                this.identifyCode +=

                    this.identifyCodes[

                        this.randomNum(0, this.identifyCodes.length)

                    ]

            }

        },

        //生成随机数

        randomNum(min, max) {

            return Math.floor(Math.random() * (max - min) + min)

        }

    }

}

</script>
//这里我安装的是scss,如果没有按钮也可以删除

<style lang="scss" scoped>

.login-btn {

    width: 100%;

    border-radius: 3px;

    height: 40px;

}

.font {

    margin-left: 3px;

}


.login-icon {

    width: 15px;

    height: 15px;

}


body {

    font-family: Microsoft YaHei, Arial, "\5b8b\4f53";

}


.clearfix:before,

.clearfix:after {

    content: "";

    display: table;

}

.clearfix:after {

    clear: both;

}


.clearfix {

    *zoom: 1;

}

.login {

    /* background: #03177A; */

    width: 100%;

    height: 100%;

    background: url("../../assets/login_images/back.jpg") no-repeat center 0px;

    background-size: cover;

    background-position: center 0;

    background-repeat: no-repeat;

    background-attachment: fixed;

    -webkit-background-size: cover;

    -o-background-size: cover;

    -moz-background-size: cover;

    -ms-background-size: cover;

    position: relative;

}

.login > .login_main {

    width: 100%;

    height: 100%;

    display: flex;

    justify-content: center;

    align-items: center;

}


.login > .login_main > .main_right {

    height: 27rem;

    width: 22rem;

    background: rgba(255, 255, 255, 0.5);

    border-radius: 10px;

    -moz-border-radius: 10px;

    -webkit-border-radius: 10px;

}

.login > .login_main > .main_right > form input:focus {

    border: 1px solid #9ec6ff !important;

}



.login > .login_main > .main_right > .right_title {

    letter-spacing: 2px;

    color: #2a82ff;

    font-size: 32px;

    text-align: center;

    line-height: 60px;

    margin: 30px auto;

    font-weight: 500;

    font-family: Verdana, Geneva, Tahoma, sans-serif;

    background-image: -webkit-linear-gradient(bottom, red, #fd8403, yellow);

    -webkit-background-clip: text;

    -webkit-text-fill-color: transparent;

}



.login > .login_main > .main_right > form > div {

    position: relative;

}



.login > .login_main > .main_right > form > div > img {

    position: absolute;

    left: 15px;

    top: 10px;

}



.login > .login_main > .main_right > form input {

    height: 35px;

    width: 100%;

    border: 1px solid #d3d8dc;

    box-sizing: border-box;

    margin-bottom: 30px;

    border-radius: 3px;

    color: #333;

    padding-left: 40px;

    -moz-border-radius: 3px;

    -webkit-border-radius: 3px;

}



.login > .login_main > .main_right > form > .code > input {

    width: 69%;

}



.login > .login_main > .main_right > form > .code > .code_img {

    height: 35px;

    float: right;

    cursor: pointer;

}



.login > .login_main > .main_right > form input:focus {

    border: 1px solid #999;

}


.login > .login_main > .main_right > form > .yes_login > a {

    display: block;

    width: 90%;

    height: 35px;

    line-height: 35px;

    text-align: center;

    background-color: #1677ff;

    border-radius: 3px;

    color: #fff;

    text-decoration: none;

    margin-left: 15px;

    -moz-border-radius: 3px;

    -webkit-border-radius: 3px;

}



.login > .login_main > .main_right > form > .yes_login > a:hover {

    background-color: #0058af;

}



.login > .login_main > .main_right > form > .yes_cancle {

    padding-top: 10px;

}




.login > .login_footer {

    text-align: center;

    padding-top: 130px;

}




.login > .login_footer > p {

    font-size: 14px;

    color: #eee;

    line-height: 30px;

}

</style>

图片素材

code.png

login.png

pwd.png back.jpg

注意: 里面的图片地址要放在正确的路径上,不然可能会报错