vue3纯前端验证码示例
前言
- 验证码的用途:通过要求用户输入一串难以被机器自动识别的字符或图像,有效阻止恶意用户或脚本通过暴力破解方式尝试登录账户。
- 验证码的分类:常见的验证码有短信、文本、图形等,安全度越高,依赖的插件或服务也越多。
今天我们来做一个简单的纯前端字符验证码码组件,不需要插件,仅做为示例。
先看一下效果:
分析
一个简单的字符验证码,只需求定义一个字符集,一个随机生成函数就可以了。如果要再进一步增加一些效果,如干扰线,干扰点,则需要借助Canvas来进行绘制,以增强可视化效果。
基础代码示例
以下代码就完成了简单验证码的核心工作,生成指定位数的随机验证码。
// 生成校验码
const makeCode = (len = 4) => {let code = "";const codeLength = len; //验证码的长度// 定义生成验证码的字符集,去除易混淆的字符集1il0oOconst identifyCodes = "123456789abcdefjhijkinpqrsduvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";for (let i = 0; i < codeLength; i++) {// 获取随机字符code += identifyCodes[randomNum(0, identifyCodes.length)];}return code; //把code值赋给验证码
};
//随机数生成:根据角标拿字符串的值
const randomNum = (min = 0, max: number) => Math.floor(Math.random() * (max - min)) + min;
组件化及可视化增强
下面我们来做一个完整的vue验证码组件,并借助Canvas添加干扰线和干扰点的效果。
既然是组件,就需要几个参数供调用者调整,常规的就是组件的宽、高、字号以及是否需要干扰线或干扰点,所以这里只定义了这几个参数。
多余的就不说了,直接上代码。
1、vue验证码组件代码:
<template><div class="s-canvas"><canvasid="s-canvas":width="contentWidth":height="contentHeight"@click="refreshCode"></canvas></div>
</template>
<script lang="ts" setup>
import { ref, onMounted, withDefaults, defineProps } from "vue";// 定义props类型
interface CodeProps {/** 默认验证码 */defaultCode?: string;/** 容器宽度 */contentWidth?: number;/** 容器高度 */contentHeight?: number;/** 最大干扰线,0时无干扰线 */maxLine?: number;/** 最大干扰点,0时无干扰点 */maxDot?: number;/** 字体最小值 */fontSizeMin?: number;/** 字体最大值 */fontSizeMax?: number;
}
// props默认值
const props = withDefaults(defineProps<CodeProps>(), {contentWidth: 90,contentHeight: 30,fontSizeMin: 25,fontSizeMax: 30,maxLine: 4,maxDot: 10,
});const emit = defineEmits(["update:verifyCode"]);
//验证码
const verifyCode = ref("");onMounted(() => {verifyCode.value = props.defaultCode || makeCode();emit("update:verifyCode", verifyCode.value);drawPic(verifyCode.value);
});
// 生成校验码
const makeCode = (len = 4) => {let code = "";const codeLength = len; //验证码的长度// 定义生成验证码的字符集,去除易混淆的字符集1il0oOconst identifyCodes = "123456789abcdefjhijkinpqrsduvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";for (let i = 0; i < codeLength; i++) {// 获取随机字符code += identifyCodes[randomNum(0, identifyCodes.length)];}return code; //把code值赋给验证码
};// 重置验证码
const refreshCode = () => {verifyCode.value = makeCode();emit("update:verifyCode", verifyCode.value);drawPic(verifyCode.value);
};
// 定义暴露接口
// defineExpose({ refreshCode });//随机数生成:根据角标拿字符串的值
const randomNum = (min = 0, max: number) => Math.floor(Math.random() * (max - min)) + min;// 生成一个随机的颜色
function randomColor(min: number, max: number) {let r = randomNum(min, max);let g = randomNum(min, max);let b = randomNum(min, max);return "rgb(" + r + "," + g + "," + b + ")";
}
/** 绘制文字 */
function drawPic(verifyCode: string) {let canvas = document.getElementById("s-canvas") as HTMLCanvasElement;if (!canvas) {console.error("找不到 canvas 元素");return;}//创建一个2D对象作为上下文。let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;ctx.textBaseline = "bottom";// 绘制背景ctx.fillStyle = "#e6ecfd";ctx.fillRect(0, 0, props.contentWidth, props.contentHeight);// 绘制文字for (let i = 0; i < verifyCode.length; i++) {drawText(ctx, verifyCode, i);}drawLine(ctx, props.maxLine);drawDot(ctx, props.maxDot);
}/**在画布上显示数据* @param ctx CanvasRenderingContext2D* @param verifyCode 要显示的文字* @param index 字符索引*/
function drawText(ctx: CanvasRenderingContext2D, verifyCode: string, index: number) {ctx.fillStyle = randomColor(50, 160); // 随机生成字体颜色ctx.font = randomNum(props.fontSizeMin, props.fontSizeMax) + "px SimHei"; // 随机生成字体大小let x = (index + 1) * (props.contentWidth / (verifyCode.length + 1));let y = randomNum(props.fontSizeMax, props.contentHeight - 5);var deg = randomNum(-10, 15);// 修改坐标原点和旋转角度ctx.translate(x, y);ctx.rotate((deg * Math.PI) / 180);ctx.fillText(verifyCode[index], 0, 0);// 恢复坐标原点和旋转角度ctx.rotate((-deg * Math.PI) / 180);ctx.translate(-x, -y);
}
/** 绘制干扰线* @param ctx CanvasRenderingContext2D* @param max 最大干扰线个数*/
function drawLine(ctx: CanvasRenderingContext2D, maxLine = 4) {if (maxLine <= 0) {return;}for (let i = 0; i < maxLine; i++) {ctx.strokeStyle = randomColor(150, 200);ctx.beginPath();ctx.moveTo(randomNum(0, props.contentWidth), randomNum(0, props.contentHeight));ctx.lineTo(randomNum(0, props.contentWidth), randomNum(0, props.contentHeight));ctx.stroke();}
}
/** 绘制干扰点* @param ctx CanvasRenderingContext2D* @param max 最大干扰点个数*/
function drawDot(ctx: CanvasRenderingContext2D, maxDot = 10) {if (maxDot <= 0) {return;}for (let i = 0; i < maxDot; i++) {ctx.fillStyle = randomColor(0, 255);ctx.beginPath();ctx.arc(randomNum(0, props.contentWidth), randomNum(0, props.contentHeight), 1, 0, 2 * Math.PI);ctx.fill();}
}
</script>
2、使用验证码组件
代码可直接复制进行验证,ui使用了ant-design-vue,如果用的不是ant,则直接替换组件即可。
<template><div class="main"><div class="container"><div><a-input placeholder="请输入验证码" v-model:value="code"></a-input></div><div><!--验证码组件--><VerifyCode v-model:verifyCode="identifyCode"></VerifyCode></div></div><div><p>当前验证码: {{ identifyCode }},手动输入验证码: {{ code }}</p><a-button type="primary" @click="submit">提交</a-button></div></div>
</template><script lang="ts" setup>
import { ref, onMounted } from "vue";
import { message } from "ant-design-vue";
import VerifyCode from "./verifyCode.vue";
// 验证码输入框内容
let code = ref("");
// 验证码图片内容
let identifyCode = ref("");
function submit() {if (code.value == "") {message.error("请先输入验证码");return;}if (identifyCode.value == code.value) {message.success("验证码正确✓");} else {message.error("验证码错误,请重新输入!");}
}
</script>
<style lang="less" scoped>
.main {padding: 20px;
}
.container {display: flex;flex-direction: row;align-items: flex-start;justify-content: center;
}
</style>
注意事项:
- 通过
update:verifyCode:来实现验证码的自动回填,减少了业务使用方的数据交互处理。
最终效果

相关文章:
vue3纯前端验证码示例
前言 验证码的用途:通过要求用户输入一串难以被机器自动识别的字符或图像,有效阻止恶意用户或脚本通过暴力破解方式尝试登录账户。验证码的分类:常见的验证码有短信、文本、图形等,安全度越高,依赖的插件或服务也越多…...
招聘程序员
全栈总监❤️golang❤️UI设计师 ☀️前端☀️Nodejs工☀️平面设计☀️PHP工 ☀️安卓❤️Flutter❤️运维☀️爬虫 公司福利: ☃️ 带薪年假、年终奖、13k-18k薪 🏩 内宿 2人/间或外宿可补助 💵 转正绩效 ✨节日礼金:生日礼金…...
Android 判断手机放置的方向
#1024程序员节|征文# 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 需求 老板:我有个手持终端,不能让他倒了,当他倒或者倾斜的时候要发出报警; 程序猿:我这..... 老板…...
Telegram机器人的手机部署
目的 一直有读 epub 电子书的习惯,摘录段落复制下来段落很难看,把自己写的排版器的逻辑复制下来,写成了一个排版机器人所有发给机器人的文字,都会经过排版,后转发到读书频道 前提 本来最好方法是直接把机器人架在服…...
ffmpeg视频滤镜: 色温- colortemperature
滤镜简述 colortemperature 官网链接 》 FFmpeg Filters Documentation 这个滤镜可以调节图片的色温,色温值越大显得越冷,可以参考一下下图: 咱们装修的时候可能会用到,比如选择灯还有地板的颜色的时候,选暖色调还是…...
Django+Vue全栈开发项目入门(二)
Vue是一款用于构建用户界面的JavaScript渐进式框架,它基于标准HTML、CSS和JavaScript构建,并提供了一套声明式的、响应式的、组件化的编程模型,有助于高效地开发用户界面。 环境准备 安装Node.js:Vue项目的构建和运行依赖于Node…...
【ubuntu改源】
ubuntu改源 备份原始源查看ubuntu发行版本arm64 noble版本的源vim修改源更新系统软件源 备份原始源 sudo cp /etc/apt/sources.list /etc/apt/sources.list.disabled查看ubuntu发行版本 lsb_release -aarm64 noble版本的源 清华源 vim修改源 esc :1,$d # 删除所有# 默认注…...
SQLI LABS | Less-9 GET-Blind-Time based-Single Quotes
关注这个靶场的其它相关笔记:SQLI LABS —— 靶场笔记合集-CSDN博客 0x01:过关流程 输入下面的链接进入靶场(如果你的地址和我不一样,按照你本地的环境来): http://localhost/sqli-labs/Less-9/ 靶场提示 …...
【小白学机器学习24】 用例子来比较:无偏估计和有偏估计
目录 1 关于无偏估计 1.1 无偏估计的定义 2 原始数据 2.1 假设我们是上帝,我们能创造一个总体/母体 population 2.2 按尽量随机取样的原则去取1个随机样本 sample1 3 一个关于无偏估计的理解 3.1 接着上面的总体和样本 sample1 3.2 左边的计算,期…...
C++在实际项目中的应用第二节:C++与网络编程
第五章:C在实际项目中的应用 第二节:C与网络编程 1. TCP/IP协议详解与C实现 TCP/IP(传输控制协议/互联网协议)是现代互联网通信的基础协议。理解 TCP/IP 协议对于开发网络应用至关重要。本节将详细介绍 TCP/IP 协议的工作原理以…...
依赖关系是危险的
依赖, 我们需要它们,但如何有效安全地使用它们?在本周的节目中,Kris 与 Ian 和 Johnny 一起讨论了 polyfill.io 供应链攻击、Go 中依赖管理和使用的历史,以及 Go 谚语“一点复制胜过一点依赖”。当然,我们用一些不受欢…...
ipguard与Ping32如何加密数据防止泄露?让企业信息更安全
在信息化时代,数据安全已成为企业运营的重中之重。数据泄露不仅会导致经济损失,还可能损害企业声誉。因此,选择合适的数据加密工具是保护企业敏感信息的关键。本文将对IPGuard与Ping32这两款加密软件进行探讨,了解它们如何有效加密…...
gitlab 的备份与回复
一、gitlab备份 1.确定备份目录 gitlab 默认的备份目录为/var/opt/gitlab/backups,可通过配置gitlab.rb配置文件进行修改,如: [rootlocalhost ~]# vim /etc/gitlab/gitlab.rb #若要修改备份文件的存储目录话,打开下面选项的注释…...
创建型模式-----建造者模式
目录 背景: 构建模式UML 代码示例 房子成品: 构建器抽象: 具体构建器: 建筑师: 测试部…...
威胁 Windows 和 Linux 系统的新型跨平台勒索软件:Cicada3301
近年来,网络犯罪世界出现了新的、日益复杂的威胁,能够影响广泛的目标。 这一领域最令人担忧的新功能之一是Cicada3301勒索软件,最近由几位网络安全专家进行了分析。他们有机会采访了这一危险威胁背后的勒索软件团伙的成员。 Cicada3301的崛…...
Go 语言基础教程:7.Switch 语句
在这篇教程中,我们将学习 Go 语言中的 switch 语句,它是条件分支的重要结构。我们将通过一个示例程序逐步解析 switch 的不同用法。 package mainimport ("fmt""time" )func main() {i : 2fmt.Print("Write ", i, " …...
mysql原理、部署mysql主从+读写分离、监控mysql主从脚本
mysql:工作原理 从库生成两个线程,一个I/O线程,一个SQL线程; i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中; 主库会生成一个 log dump 线程&…...
模型选择拟合
1.通过多项式拟合交互探索概念 import math import numpy as np import torch from torch import nn from d2l import torch as d2l 2.使用三阶多项式来生成训练和测试数据的标签 max_degree 20 # 多项式的最大阶数 n_train, n_test 100, 100 # 训练和测试数据集大小 true…...
文案语音图片视频管理分析系统-视频矩阵
文案语音图片视频管理分析系统-视频矩阵 1.产品介绍 产品介绍方案 产品名称: 智驭视频矩阵深度分析系统(SmartVMatrix) 主要功能: 深度学习驱动的视频内容分析多源视频整合与智能分类高效视频检索与编辑实时视频监控与异常预警…...
ArcGIS计算落入面图层中的线的长度或面的面积
本文介绍在ArcMap软件中,计算落入某个指定矢量面图层中的另一个线图层的长度、面图层的面积等指标的方法。 如下图所示,现在有2个矢量要素集,其中一个为面要素,表示某些区域;另一个为线要素,表示道路路网。…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
