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:来实现验证码的自动回填,减少了业务使用方的数据交互处理。

最终效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/453799.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ENSP环回路由的配置

环回路由配置如下&#xff0c;网段及其基础配置已写完。为了实现全网通&#xff0c;需要给路由器手写配置&#xff0c;使用 ip route—static目标网段下一跳。把所有情况都要考虑到&#xff0c;就会出现去往一个网段的最优路径和次优路径&#xff0c;近路和远路都能前往目标网段…

Spire.PDF for .NET【页面设置】演示:在 C# 中应用 PDF 页面转换

当您在导出为 PDF 格式的文档中翻页时&#xff0c;页面过渡会显示装饰效果&#xff0c;例如溶解或擦除。当您以 PDF 格式创建幻灯片时&#xff0c;页面过渡特别有用。Spire.PDF是一款专为开发人员设计的强大 .NET 组件&#xff0c;可让您将页面过渡应用于 PDF 文件。 这里介绍…

【新专栏】Excel数据分析与模拟决策

专栏入口&#xff1a;Excel数据分析与模拟决策 主要面向使用Excel的用户&#xff0c;讲解Excel的数据分析&#xff0c;模拟分决策内容&#xff0c;内容涵盖基于Excel的统计分析&#xff0c;数据生成&#xff0c;采样&#xff0c;假设检验&#xff0c;线性回归&#xff0c;线性规…

大语言模型(LLM)入门级选手初学教程

链接&#xff1a;https://llmbook-zh.github.io/ 前言&#xff1a; GPT发展&#xff1a;GPT-1 2018 -->GPT-2&GPT-3&#xff08;扩大预训练数据和模型参数规模&#xff09;–> GPT-3.5&#xff08;代码训练、人类对齐、工具使用等&#xff09;–> 2022.11 ChatG…

海外云手机:出海电商养号智能化方案

随着出海电商的迅猛发展&#xff0c;使用海外云手机进行养号已经成为越来越多商家的新选择。尤其在社交电商推广和短视频引流方面&#xff0c;海外云手机不仅提高了流量的精准度&#xff0c;还助力商家实现业务的快速增长。本文将探讨海外云手机养号相较于传统模式的优势&#…

STM32CubeIDE(Eclipse)Post-build steps添加带参.exe实现全流程(1):带参.exe制作

0 工具准备 vscode&#xff0c;编辑C代码 Code Runner插件&#xff0c;用于生成exe 1 前言 使用STM32CubeIDE编译生成了二进制镜像文件后&#xff0c;有时为了防止镜像被恶意修改&#xff0c;可以通过添加校验和来对整个镜像进行保护&#xff0c;实现手段就是在STM32CubeIDE工…

精华分享 | 大模型LLM微调技巧与实践总结

导读 本文总结了作者在ChatGLM-6B模型微调的经验&#xff0c;并汇总了目前开源项目&数据。 写在前面 大型语言模型横行&#xff0c;之前非常焦虑&#xff0c;现在全面拥抱。目前也有很多开源项目进行大模型微调等&#xff0c;笔者也做了一阵子大模型了&#xff0c;特此来…

datawhale大模型bot应用开发--task4:图片流

一、图像流是专门用于图像处理的一个流程工具 在图像流中&#xff0c;你可以通过可视化的操作方式灵活添加各种用于图像处理的节点&#xff0c;构建一个图像处理流程来最终生成一个图像。图像流发布后&#xff0c;支持在 Bot 或工作流中使用。 二、图像流的能力范围 类型 图…

【Linux】进程--详细解释进程

目录 1、冯诺依曼体系结构 2、操作系统 3、进程 4、环境变量 5、进程地址空间 6、页表&#xff08;简单初步理解&#xff09; 1、冯诺依曼体系结构 a、存储器指的是&#xff1a;内存 外设&#xff1a; b、输入设备&#xff1a;鼠标&#xff0c;键盘&#xff0c;摄像头&am…

宠物用品在线交易:SpringBoot开发实战

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

Python入门(一)

心血来潮就干&#xff1a;python课程走起 和你一起学习 Python 语言的基础语法。你将会系统性地学习 Python 基础知识&#xff1b; 直接开始吧&#xff5e; 本篇文章将了解编程的几个基础概念。并且&#xff0c;你将学到如何在电脑屏幕上输出数字、文字&#xff0c;并敲出你…

ChatGLM4重磅开源! 连忙实操测试一波,效果惊艳,真的好用!附带最新相关资料和喂饭级实操推理教程!!

本文目录 GLM4重磅开源啦 GLM4系列版本介绍 GLM4大模型能力测评结果 经典测评任务结果 长文本能力 工具调用能力 多模态能力 手把手实操GLM-4-9B-Chat推理预测&&效果展示 GLM4运行硬件和环境要求 配置对应的库环境 使用peftbitsandbytes 进行4位量化推理 进…

Java基础12-特殊文件和日志技术

十二、特殊文件和日志技术 1、特殊文件 properties&#xff1a;用来存储键值对数据。 xml&#xff1a;用来存储有关系的数据。 1.1 properties文件 特点&#xff1a;存储键值对&#xff0c;键不能重复&#xff0c;文件后缀一般是.properties结尾的。 properties&#xff1a;是…

Docker设置日志滚动

问题描述 Docker 容器中的进程会将打印到控制台(console)的日志保存到容器的目录下&#xff0c;默认的 Docker 配置不带有日志的回滚。会在自己的容器目录下往同一个日志文件中不停写入&#xff0c;最后会导致磁盘空间占满的问题。 解决方案 方案一&#xff1a;全局范围内修…

利用Docker搭建一套Mycat2+MySQL8一主一从、读写分离的最简单集群(保姆教程)

文章目录 1、Mycat介绍1.1、mycat简介1.2、mycat重要概念1.3、Mycat1.x与Mycat2功能对比1.2、主从复制原理 2、前提准备3、集群规划4、安装和配置mysql主从复制4.1、master节点安装mysql8容器4.2、slave节点安装mysql8容器4.2、配置主从复制4.3、测试主从复制配置 5、安装mycat…

微信小程序canvas 生成二维码图片,画图片,生成图片,将两个canvas结合并保存图片

**需求实现步骤如下 先定义两个canvas一个canvas myQrcode画二维码的图片另一个canvas mycanvas画一个背景图&#xff0c;并把二维码画到这个canvas上&#xff0c;mycanvas这个canvas生成一张图片&#xff0c;返回图片的临时路径最后保存图片到手机** 首先wxml,新版微信小程序…

【SpringCloud】04-Gateway网关登录校验

1. 网关请求处理流程 2. 网关过滤器 3. 网关实现登录校验 Component // 参数构造器 RequiredArgsConstructor public class AuthGlobalFilter implements GlobalFilter, Ordered {private final AuthProperties authProperties;private final JwtTool jwtTool;private final A…

数据结构——笛卡尔树详解

数据结构——笛卡尔树 1&#xff0c;笛卡尔树的介绍2&#xff0c;笛卡尔树的构建3&#xff0c;笛卡尔树的代码实现 1&#xff0c;笛卡尔树的介绍 前面我们讲过《堆》和《二叉搜索树》&#xff0c;能不能把这两种数据结构的特性结合起来构造一棵新的树呢&#xff1f;当然是可以…

Qt-界面优化控件样式设置(72)

目录 描述 QPushButton 自定义复选框 输入框 列表框 菜单 实现登入界面 设置背景图 改变样式表 描述 这里介绍一些控件的样式设置 QPushButton 相关属性 font-size设置⽂字⼤⼩.border-radius设置圆⻆矩形. 数值设置的越⼤, ⻆就 "越圆".background-colo…

离散数学 第二讲 特殊集合和集合间关系 笔记 [电子科大]王丽杰

1.2 特殊集合与集合间关系 空集 不含任何元素的集合叫做空集(empty set)&#xff0c;记作∅. 空集可以符号化为 ∅ { x ∣ x ≠ x } ∅ \{ x|x ≠ x\} ∅{x∣xx} . 空集是绝对唯一的。 全集 针对一个具体范围&#xff0c;我们考虑的所有对象的集合叫做全集(universal se…