当前位置: 首页 > news >正文

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>

这个组件中,我们使用了 Arrayfill 方法,来创建一个长度为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>其中&#xff1a; user、password&#…...

git报错:Error merging: refusing to merge unrelated histories

碰对了情人&#xff0c;相思一辈子。 打命令&#xff1a;git pull origin master --allow-unrelated-histories 然后等一会 再push 切记不要有冲突的代码 需要改掉~...

QT-QLabel显示图片,按QLabel控件的大小自动缩放

要按照 QLabel 控件的大小调整并显示图片&#xff0c;你可以使用 scaled() 函数将 QPixmap 对象进行缩放&#xff0c;然后将缩放后的图片设置到 QLabel 上。下面是一个示例代码&#xff1a; #include <QApplication> #include <QLabel> #include <QPixmap>i…...

【JS代码调试技巧】你必须知道的Javascript技巧汇总

注&#xff1a;最后有面试挑战&#xff0c;看看自己掌握了吗 文章目录 使用控制台检查变量值控制台使用 type of 检查变量的类型捕获拼错的变量名和函数名捕获使用赋值运算符而不是相等运算符捕捉函数调用后缺少的左括号和右括号 &#x1f338;I could be bounded in a nutshel…...

JAVA-@Configuration注解属性proxyBeanMethods

Configuration注释中的proxyBeanMethods参数是springboot1.0&#xff0c;升级到springboot2.0之后新增的比较重要的内容&#xff0c;该参数是用来代理bean的。 理论 首先引出两个概念&#xff1a;Full 全模式&#xff0c;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在输出模式&#xff0c;禁止使用内部上下拉 F4/F7/H7在输出模式&#xff0c;可以使用内部上下拉不同系列IO翻转速度不同 F1系列的IO端口 施密特触发器&#xff1a;将非标准方波&#xff0c;整形为方波 当…...

华为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 …...

面试热题(打家窃舍)

一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存放金额的非负…...

【Deepsort】C++版本Deepsort编译(依赖opencv,eigen3)

目录 下载源码安装onnxruntime安装Eigen3编译opencv 下载源码 https://github.com/shaoshengsong/DeepSORT安装onnxruntime 安装方法参考博客 安装Eigen3 当谈及线性代数计算库时&#xff0c;Eigen3是一个强大而受欢迎的选择。Eigen3是一个C模板库&#xff0c;提供了许多用…...

Synchronized锁升级过程

无锁状态&#xff08;无锁&#xff09;&#xff1a;当一个线程访问一个没有被锁定的Synchronized代码块时&#xff0c;处于无锁状态。此时&#xff0c;线程可以直接进入临界区执行代码&#xff0c;不需要进行任何锁协调。 偏向锁状态&#xff08;偏向锁&#xff09;&#xff1…...

汽车电子功能安全

功能安全考虑 分析方法&#xff1a;FMEA&#xff0c;DFMEA&#xff08;设计潜在失效模式和影响分析&#xff09; 严重度&#xff08;Severity&#xff09;&#xff0c;暴露率&#xff08;Exposure&#xff09;&#xff0c;可控性&#xff08;Controllability&#xff09;评估…...

ARM进阶:内存屏障(DMB/DSB/ISB)的20个使用例子详解

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

Cpp学习——模板

模板&#xff1f; 目录 模板&#xff1f; 1.介绍 2.函数模板的使用 3.函数模板的强制转换or显式调用 四,模板的分类 1.介绍 在Cpp3.0中&#xff0c;祖师爷便引入了模板的概念。这是一个重大的变革&#xff0c;为后来的Cpp标准化打下了铺垫。也正是因为有了模板&#xff0…...

HTTP 协议 版本详解

HTTP 协议 介绍<一> 简介 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于在客户端和服务器之间进行通信的协议。它是现代互联网中最常用的应用层协议之一。HTTP 的主要目的是实现超文本资源的传输&#xff0c;例如 HTML 文档、图像和音频文件等。…...

PHP语言基础知识(超详细)

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

Flex弹性盒子的项目属性

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

广州银行信用卡中心:强化数字引擎安全,实现业务稳步增长

广州银行信用卡中心是全国城商行中仅有的两家信用卡专营机构之一&#xff0c;拥有从金融产品研发至销售及后期风险控制、客户服务完整业务链条&#xff0c;曾获“2016年度最佳创新信用卡银行”。 数字引擎驱动业务增长 安全左移降低开发风险 近年来&#xff0c;广州银行信用卡…...

【Rust日报】2023-08-03 - Polars 获约 400 万美元种子轮融资

文章&#xff1a;2023 年对 Rust 编译器 CI 的改进 kobzol 的新文章&#xff0c;介绍了关于优化 Rust 编译器构建、测试和性能监视基础设施的方案和实施情况。 根据作者的工作&#xff0c;文章内容分为三类&#xff1a; Rust 编译器&#xff08;rustc&#xff09;构建配置、 Ru…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...