Vue3实现6位验证码输入框,用户可以连续输入和删除
实现代码
可以随意填写删除
<template><div class="verification-container"><inputv-for="(code, index) in verificationCodes":key="index"v-model="verificationCodes[index]"@input="handleInput(index, $event)"@keydown="handleKeyDown(index, $event)"maxlength="1"class="verification-input"/></div>
</template><script>
import { ref, nextTick } from 'vue';export default {setup() {const verificationCodes = ref(['', '', '', '', '', '']);const handleInput = (index, event) => {const value = event.target.value;verificationCodes.value[index] = value;// 自动跳到下一个输入框if (value && index < verificationCodes.value.length - 1) {const nextInput = event.target.nextElementSibling;if (nextInput) {nextTick(() => {nextInput.focus();});}}};const handleKeyDown = (index, event) => {// 处理删除操作if (event.key === 'Backspace' && !event.target.value && index > 0) {const prevInput = event.target.previousElementSibling;if (prevInput) {nextTick(() => {prevInput.focus();});}}};return {verificationCodes,handleInput,handleKeyDown};}
};
</script><style lang="scss" scoped>
.verification-container {display: flex;
}.verification-input {width: 40px;height: 40px;margin-right: 10px;text-align: center;font-size: 18px;border: 1px solid #ccc;border-radius: 5px;
}.verification-input:focus {outline: none;border-color: #007bff;box-shadow: 0 0 5px #007bff;
}
</style>
在更新后的代码中,我们添加了一个新的handleKeyDown方法来处理键盘按键事件。如果用户按下了 "Backspace" 键并且当前输入框为空,则将焦点设置到前一个输入框。
通过这个更改,当用户输入一半时,按下 "Backspace" 键会自动删除前一个输入框中的内容,并将焦点移动到前一个输入框,以允许用户重新输入。
请注意,我们使用了nextTick函数来确保在下一个DOM更新周期后设置焦点,以避免与Vue的响应式更新冲突。
希望这个更新后的代码能够解决问题,并允许用户在输入一半时删除前面的内容。
必须输入完整才能删除内容
<template><div class="verification-container"><inputv-for="(code, index) in verificationCodes":key="index"v-model="verificationCodes[index]"@input="handleInput(index, $event)"maxlength="1"class="verification-input"/></div>
</template>
<script>
import { ref } from 'vue';export default {setup() {const verificationCodes = ref(['', '', '', '', '', '']);const handleInput = (index, event) => {const value = event.target.value;verificationCodes.value[index] = value;// 自动跳到下一个输入框if (value && index < verificationCodes.value.length - 1) {const nextInput = event.target.nextElementSibling;if (nextInput) {nextInput.focus();}}// 自动删除前面的内容if (!value && index > 0) {const prevInput = event.target.previousElementSibling;if (prevInput) {prevInput.focus();}}};return {verificationCodes,handleInput};}
};
</script>
<style lang="scss" scoped>
.verification-container {display: flex;
}.verification-input {width: 40px;height: 40px;margin-right: 10px;text-align: center;font-size: 18px;border: 1px solid #ccc;border-radius: 5px;
}.verification-input:focus {outline: none;border-color: #007bff;box-shadow: 0 0 5px #007bff;
}
</style>
使用v-for指令生成6个输入框,并将每个输入框的值绑定到verificationCodes数组中的对应索引位置。我们还使用@input事件监听输入框的输入,并调用handleInput方法处理输入事件。
在组件的逻辑部分,定义verificationCodes数组,并实现handleInput方法。
代码中,我们使用ref创建了一个名为verificationCodes的响应式数组,用于保存每个输入框的值。在handleInput方法中,我们更新对应索引位置的值,并根据输入的情况自动跳到下一个输入框或删除前面的内容。我们使用focus()方法将焦点设置到下一个或前一个输入框
残缺版代码
<template><div class="custom-class"><!-- <inputv-for="(item, index) in nums":key="index"v-model="nums[index]"maxlength="1":ref="`input${index}`"@keydown="onKeyDown(index, $event)"@input="handleInput(index)"@focus="onFocus(index)"/> --><inputv-model="nums[0]"maxlength="1"ref="input0"@keydown="onKeyDown(0, $event)"@input="handleInput(0)"@focus="onFocus(0)"/><inputv-model="nums[1]"maxlength="1"ref="input1"@keydown="onKeyDown(1, $event)"@input="handleInput(1)"@focus="onFocus(1)"/><inputv-model="nums[2]"maxlength="1"ref="input2"@keydown="onKeyDown(2, $event)"@input="handleInput(2)"@focus="onFocus(2)"/><inputv-model="nums[3]"maxlength="1"ref="input3"@keydown="onKeyDown(3, $event)"@input="handleInput(3)"@focus="onFocus(3)"/><inputv-model="nums[4]"maxlength="1"ref="input4"@keydown="onKeyDown(4, $event)"@input="handleInput(4)"@focus="onFocus(4)"/><inputv-model="nums[5]"maxlength="1"ref="input5"@keydown="onKeyDown(5, $event)"@input="handleInput(5)"@focus="onFocus(5)"/></div>
</template><script setup>
import {defineProps,getCurrentInstance,reactive,ref,nextTick,watch,computed,
} from "vue";
const internalInstance = getCurrentInstance();defineProps({isShowSecuityDia: Boolean,
});let nums = reactive(["", "", "", "", "", ""]);
// const currentInput = ref(0);
// const input0 = ref(null);
// const input1 = ref(null);
// const input2 = ref(null);
// const input3 = ref(null);
// const input4 = ref(null);
// const input5 = ref(null);// nextTick(() => {
// // input0.value.focus();
// currentInput.value++;
// // console.log(["input" + currentInput.value].value, "123");
// // console.log(input0.value.value);
// });// watch(
// nums,
// () => {
// console.log(currentInput.value, 888);
// if (currentInput.value === 1) {
// currentInput.value += 1;
// input1.value.focus();
// } else if (currentInput.value === 2) {
// currentInput.value += 1;
// input2.value.focus();
// } else if (currentInput.value === 3) {
// currentInput.value += 1;
// input3.value.focus();
// } else if (currentInput.value === 4) {
// currentInput.value += 1;
// input4.value.focus();
// } else if (currentInput.value === 5) {
// currentInput.value += 1;
// input5.value.focus();
// }
// },
// { deep: true }
// );// const emits = defineEmits(["changeRemDialog"]);
// const confirmSubmit = () => {
// let code = nums.join("");
// nums = reactive(["", "", "", "", "", ""]);
// emits("changeRemDialog", code);
// };let activeIndex = 0;const onKeyDown = (index, e) => {// console.log(index, e, activeIndex, 888);switch (e.keyCode) {case 8: // backspace键e.preventDefault();if (nums[index]) {nums[index] = "";if (index > 0) {activeIndex = index - 1;const prevInput = internalInstance.ctx.$refs[`input${index - 1}`];prevInput.focus();}} else if (index === 0) {activeIndex = 0;}break;default:break;}
};const handleInput = (index) => {// console.log(index, activeIndex, 999);if (nums[index]) {activeIndex = index;if (index < 5) {const nextInput = internalInstance.ctx.$refs[`input${index + 1}`];nextInput.focus();}}
};const onFocus = (index) => {activeIndex = index;
};// const deleteLastNum = () => {
// if (currentInput.value === 6) {
// input5.value.focus();
// currentInput.value + -1;
// } else if (currentInput.value === 5) {
// input4.value.focus();
// currentInput.value + -1;
// }
// };// 把六个数字拼接成一个变量
const code = computed(() => {return nums.join("");
});
// console.log(code);
</script>
<style lang="scss" scoped>
.custom-class {display: flex;justify-content: space-between;align-items: center;input {width: 75px;height: 75px;background: #ffffff;border: 1px solid #d9d9d9;border-radius: 12px;font-size: 40px;// caret-color: rgba(0, 0, 0, 0);}
}
</style>
以下是一个简单的 Vue3 组件来实现6位验证码输入框的功能,其中用户可以连续输入和删除。
<template><div class="verification-code"><inputv-for="(item, index) in codeList":key="index":ref="`codeInput${index}`"v-model.trim="codeList[index]":class="{ 'code-active': activeIndex === index }"@keydown="onKeyDown(index, $event)"@input="onInput(index)"@focus="onFocus(index)"/></div>
</template><script>
import { defineComponent } from 'vue';export default defineComponent({name: 'VerificationCode',setup(props, { emit }) {const codeList = Array(6).fill('').map((item) => item);let activeIndex = 0;const onKeyDown = (index, e) => {switch (e.keyCode) {case 8: // backspace键e.preventDefault();if (codeList[index]) {codeList[index] = '';if (index > 0) {activeIndex = index - 1;const prevInput = $refs[`codeInput${index - 1}`];prevInput.focus();}} else if (index === 0) {activeIndex = 0;}break;default:break;}};const onInput = (index) => {if (codeList[index]) {activeIndex = index + 1;if (activeIndex < 6) {const nextInput = $refs[`codeInput${activeIndex}`];nextInput.focus();}}};const onFocus = (index) => {activeIndex = index;};return {codeList,activeIndex,onKeyDown,onInput,onFocus};}
});
</script><style scoped>
.verification-code {display: flex;justify-content: center;align-items: center;
}input {width: 4em;height: 4em;margin: 0 0.5em;font-size: 2em;text-align: center;border: 1px solid #ccc;border-radius: 5px;
}input:focus {outline: none;
}.code-active {border-color: #007fff;
}
</style>
使用该组件的示例:
<template><div class="app"><verification-code /></div>
</template><script>
import VerificationCode from './components/VerificationCode.vue';export default {name: 'App',components: {VerificationCode}
};
</script><style>
.app {display: flex;justify-content: center;align-items: center;height: 100vh;
}
</style>
这个组件中,我们使用了
Array
的fill
方法,来创建一个长度为6、每个元素都为空字符串的数组codeList
。然后,我们使用v-for
循环这个数组,为每个元素创建一个输入框,并为其绑定v-model
实现双向数据绑定。我们还绑定了@keydown
事件来监听用户按键操作,以及@input
和@focus
事件来监听输入和焦点变化。在
onKeyDown
函数中,我们首先判断是否按下的是 backspace 键,如果是,我们会阻止默认行为,然后检查当前输入框是否为空字符串。如果不为空,我们会将其置为空字符串,然后检查当前输入框的索引是否大于0。如果是,我们会将activeIndex
设置为当前输入框的索引减一,并将光标移动到前一个输入框。如果当前输入框的索引已经是0,我们会将activeIndex
设置为0,以确保用户可以从第一个输入框开始删除验证码。在
onInput
函数中,我们先检查当前输入框是否已经输入了值。如果是,我们会将activeIndex
设置为当前输入框的索引加一,并将光标移到下一个输入框。在
onFocus
函数中,我们将activeIndex
设置为当前输入框的索引,以确保用户可以通过 tab 键和鼠标点击等操作来移动光标。
相关文章:

Vue3实现6位验证码输入框,用户可以连续输入和删除
实现代码 可以随意填写删除 <template><div class"verification-container"><inputv-for"(code, index) in verificationCodes":key"index"v-model"verificationCodes[index]"input"handleInput(index, $event…...

如何在终端设置代理(设置jupyter notebook同理)
设置代理 在终端(我用的gitbash)下执行 set HTTP_PROXYhttp://<user>:<password><proxy server>:<proxy port> set HTTPS_PROXYhttp://<user>:<password><proxy server>:<proxy port>其中: user、password&#…...

git报错:Error merging: refusing to merge unrelated histories
碰对了情人,相思一辈子。 打命令:git pull origin master --allow-unrelated-histories 然后等一会 再push 切记不要有冲突的代码 需要改掉~...
QT-QLabel显示图片,按QLabel控件的大小自动缩放
要按照 QLabel 控件的大小调整并显示图片,你可以使用 scaled() 函数将 QPixmap 对象进行缩放,然后将缩放后的图片设置到 QLabel 上。下面是一个示例代码: #include <QApplication> #include <QLabel> #include <QPixmap>i…...

【JS代码调试技巧】你必须知道的Javascript技巧汇总
注:最后有面试挑战,看看自己掌握了吗 文章目录 使用控制台检查变量值控制台使用 type of 检查变量的类型捕获拼错的变量名和函数名捕获使用赋值运算符而不是相等运算符捕捉函数调用后缺少的左括号和右括号 🌸I could be bounded in a nutshel…...
JAVA-@Configuration注解属性proxyBeanMethods
Configuration注释中的proxyBeanMethods参数是springboot1.0,升级到springboot2.0之后新增的比较重要的内容,该参数是用来代理bean的。 理论 首先引出两个概念:Full 全模式,Lite 轻量级模式 Full(proxyBeanMethods true) :pro…...
锁策略, cas 和 synchronized 优化过程总结
目录 一、锁策略 1. 乐观锁和悲观锁 2. 读写锁 3. 重量级锁和轻量级锁 4. 自旋锁 5. 公平锁和非公平锁 6.可重入锁 vs 不可重入锁 二、CAS 1. CAS 是怎么实现的 1) 实现原子类 2) 实现自旋锁 3. CAS 的 ABA 问题 三、Synchronized 原理 1.Synchronized 加锁工作过程 3.1 偏向…...

正点原子HAL库入门1~GPIO
探索者F407ZGT6(V3) 理论基础 IO端口基本结构 F4/F7/H7系列的IO端口 F1在输出模式,禁止使用内部上下拉 F4/F7/H7在输出模式,可以使用内部上下拉不同系列IO翻转速度不同 F1系列的IO端口 施密特触发器:将非标准方波,整形为方波 当…...
华为VRP 系统基础配置
1.flash 相当于电脑的 硬盘 2.NVRAM 拿来专门存放系统配置文件 3.RAM 运行内存 4.ROM 系统引导 1.修改系统名[Huawei]sysname SWL1 2.配置登入信息 [SWL1]header shell information "Welocom to the learning" [SWL1]q <SWL1>q User interface con0 …...

面试热题(打家窃舍)
一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负…...
【Deepsort】C++版本Deepsort编译(依赖opencv,eigen3)
目录 下载源码安装onnxruntime安装Eigen3编译opencv 下载源码 https://github.com/shaoshengsong/DeepSORT安装onnxruntime 安装方法参考博客 安装Eigen3 当谈及线性代数计算库时,Eigen3是一个强大而受欢迎的选择。Eigen3是一个C模板库,提供了许多用…...
Synchronized锁升级过程
无锁状态(无锁):当一个线程访问一个没有被锁定的Synchronized代码块时,处于无锁状态。此时,线程可以直接进入临界区执行代码,不需要进行任何锁协调。 偏向锁状态(偏向锁)࿱…...

汽车电子功能安全
功能安全考虑 分析方法:FMEA,DFMEA(设计潜在失效模式和影响分析) 严重度(Severity),暴露率(Exposure),可控性(Controllability)评估…...

ARM进阶:内存屏障(DMB/DSB/ISB)的20个使用例子详解
在上一节内存屏障指令之DMB、DSB和ISB详解中,介绍了一下内存屏障的三个指令的作用并举了一些例子,对于内存屏障指令的使用时机,与处理器架构(比如Cortex-M和Cortex-A)和处理器的系统实现(同样的架构,有不同的实现,如ST…...

Cpp学习——模板
模板? 目录 模板? 1.介绍 2.函数模板的使用 3.函数模板的强制转换or显式调用 四,模板的分类 1.介绍 在Cpp3.0中,祖师爷便引入了模板的概念。这是一个重大的变革,为后来的Cpp标准化打下了铺垫。也正是因为有了模板࿰…...
HTTP 协议 版本详解
HTTP 协议 介绍<一> 简介 HTTP(Hypertext Transfer Protocol)是一种用于在客户端和服务器之间进行通信的协议。它是现代互联网中最常用的应用层协议之一。HTTP 的主要目的是实现超文本资源的传输,例如 HTML 文档、图像和音频文件等。…...

PHP语言基础知识(超详细)
文章目录 前言第一章 PHP语言学习介绍 1.1 PHP部署安装环境1.2 PHP代码工具选择 第二章 PHP代码基本语法 2.1 PHP函数知识介绍2.2 PHP常量变量介绍 2.2.1 PHP变量知识:2.2.2 PHP常量知识: 2.3 PHP注释信息介绍2.4 PHP数据类型介绍 2.4.1 整形数据类型2.4…...

Flex弹性盒子的项目属性
最近在写项目时用到了弹性盒子的项目属性,记录一下,以后用到继续扩充 <div class"concern-data"><div><img src"https://meituan.thexxdd.cn/lvyou/assets/pinglun-fc62482a.svg" alt""><span>1&…...

广州银行信用卡中心:强化数字引擎安全,实现业务稳步增长
广州银行信用卡中心是全国城商行中仅有的两家信用卡专营机构之一,拥有从金融产品研发至销售及后期风险控制、客户服务完整业务链条,曾获“2016年度最佳创新信用卡银行”。 数字引擎驱动业务增长 安全左移降低开发风险 近年来,广州银行信用卡…...
【Rust日报】2023-08-03 - Polars 获约 400 万美元种子轮融资
文章:2023 年对 Rust 编译器 CI 的改进 kobzol 的新文章,介绍了关于优化 Rust 编译器构建、测试和性能监视基础设施的方案和实施情况。 根据作者的工作,文章内容分为三类: Rust 编译器(rustc)构建配置、 Ru…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...