vue3实现输入框短信验证码功能---全网始祖

组件功能分析
1.按键删除,清空当前input,并跳转prevInput & 获取焦点,按键delete,清空当前input,并跳转nextInput & 获取焦点。按键Home/End键,焦点跳转first/最后一个input输入框。ArrowLeft/ArrowRight键点击后跳转上一个/下一个输入框获取焦点。
2.判断按键为数字,则取第一个数字,然后跳转下一个input输入框获取焦点,如果为最后一个,则失去焦点,交互结束。
3.粘贴功能。通过el.clipboardData获取粘贴内容,判断是否为4/6位粘贴内容。是则赋值给页面Input,双向绑定一个数组即可。否则置为空。

代码展示

<template>
	<div class="g-remove-check-code">
		<p class="g-remove-check-code_title">发送验证码</p>
		<div class="g-remove-check-code">
        <p class="g-remove-check-code_title">
          请输入短信验证码以验证您的身份
        </p>
        <div
          class="g-remove-check-code_content"
          @keyup="fnCheckCodeKeyup"
          @keydown="fnCheckCodeKeydown"
          @paste="fnCheckCodeKeyPaste"
          @input="fnCheckCodeInputEvent"
        >
          <input :class="{'g-code-input_color': aCheckCodeInputComputed[0] !== ''}" max="9" min="0" maxlength="1" data-index="0" v-model.trim.number="aCheckCodeInputComputed[0]" type="text" ref="firstInputRef" />
          <input :class="{'g-code-input_color': aCheckCodeInputComputed[1] !== ''}" max="9" min="0" maxlength="1" data-index="1" v-model.trim.number="aCheckCodeInputComputed[1]" type="text" />
          <input :class="{'g-code-input_color': aCheckCodeInputComputed[2] !== ''}" max="9" min="0" maxlength="1" data-index="2" v-model.trim.number="aCheckCodeInputComputed[2]" type="text" />
          <input :class="{'g-code-input_color': aCheckCodeInputComputed[3] !== ''}" max="9" min="0" maxlength="1" data-index="3" v-model.trim.number="aCheckCodeInputComputed[3]" type="text" />
        </div>
      </div>
      <div class="btn-box">
        <button
          :disabled="!turnOff"
          content-text="下一步"
          @clickEvent="enter"
        />
      </div>
    </div>
</div>
</template>

<script lang="ts" setup>
import { defineComponent, ref, onMounted, onUnmounted, reactive, computed, getCurrentInstance, inject  } from "vue";
  let aCheckCodeInput = ref(["", "", "", ""]) 	// 存储输入验证码内容
  let aCheckCodePasteResult = ref([]) 	
 const turnOff = computed(() => {
    return aCheckCodeInputComputed.value.filter((v) => !!v)?.length >= 4;
  });
  onUnmounted(() => {
    clearInterval(timer.value);
  })

const enter = async () => {
    console.log("your code",aCheckCodeInputComputed.value.join("").toUpperCase())
  }
		const aCheckCodeInputComputed = computed(() => {
    if(aCheckCodePasteResult.value.length === 4) {
      return aCheckCodePasteResult.value;
    } else if (aCheckCodeInput.value && Array.isArray(aCheckCodeInput.value) && aCheckCodeInput.value.length === 4) {
      return aCheckCodeInput.value;
    } else if (/^\d{4}$/.test(aCheckCodeInput.value.toString())) {
      return aCheckCodeInput.value.toString().split("");
    } else {
      return new Array(4);
    }
  })

  // 输入验证码,更新验证码数据
  const fnCheckCodeKeyup = (e: any) => {
    let index = e?.target?.dataset.index * 1;
    let el = e.target;
    // 解决输入e的问题
    el.value = el.value
      .replace(/Digit|Numpad/i, "")
      .slice(0, 1);
    if (/Digit|Numpad/i.test(e.code)) {
      // 必须在这里赋值,否则输入框会是空值
      aCheckCodeInput.value.splice(index, 1, e.code.replace(/Digit|Numpad/i, ""));
      el.nextElementSibling && el.nextElementSibling.focus();
      if (index === 3) {
        if (aCheckCodeInput.value.join("").length === 4)  (document.activeElement as any).blur();
      }
    }
  }

  // 输入验证码,检测位置变化
  const fnCheckCodeKeydown = (e: any) =>{
    let index = e?.target?.dataset?.index * 1;
    let el = e.target;
    if (e?.key === "Backspace") {
      if (aCheckCodeInput.value[index].length > 0) {
        aCheckCodeInput.value.splice(index, 1, "");
      } else {
        if (el.previousElementSibling) {
          el.previousElementSibling.focus();
          aCheckCodeInput.value[index - 1] = "";
        }
      }
    } else if(e?.key === "Delete") {
      if (aCheckCodeInput.value[index].length > 0) {
        aCheckCodeInput.value.splice(index, 1, "");
      } else {
        if(el.nextElementSibling) {
          el.nextElementSibling.focus();
          aCheckCodeInput.value[++index] = "";
        }
      }
    } else if (e?.key === "Home") {
      el?.parentElement?.children[0] && el.parentElement.children[0].focus();
    } else if (e?.key === "End") {
      el?.parentElement?.children[aCheckCodeInput.value.length - 1] &&
      el?.parentElement?.children[aCheckCodeInput.value.length - 1].focus();
    } else if (e?.key === "ArrowLeft") {
      if (el?.previousElementSibling) el?.previousElementSibling.focus();
    } else if (e?.key === "ArrowRight") {
      if (el?.nextElementSibling) el?.nextElementSibling.focus();
    } else if(e.key === 'Enter') {
         this.doActive()
     }
  }

  // 输入验证码,解决一个输入框输入多个字符的问题
  const fnCheckCodeInputEvent = (e: any) => {
    let index = e?.target?.dataset?.index * 1;
    let el = e?.target;
    el.value = el?.value
      .replace(/Digit|Numpad/i, "")
      .slice(0, 1);
    aCheckCodeInput.value[index] = el.value;
  }

  // 验证码粘贴
  const fnCheckCodeKeyPaste = (e: any) =>{
    e?.clipboardData?.items[0].getAsString((str: string) => {
      if (str.toString().length === 4) {
        aCheckCodePasteResult.value = str.split("") as any;
        (document.activeElement as any).blur();
        aCheckCodeInput.value = aCheckCodeInputComputed.value;
        aCheckCodePasteResult.value = [];
      } else {
        // 如果粘贴内容不合规,清除所有内容
        aCheckCodeInput.value = ["", "", "", ""];
      }
    });
  }
</script>
<style scoped lang="scss">
.g-remove-check-code {
    width: 100%;
    padding: 4px 0 8px 0;
}

.g-remove-check-code .g-remove-check-code_title {
    font-size: 14px;
    color: #666;
}

.g-remove-check-code .g-remove-check-code_content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 400px;
    padding: 28px 0 28px 0;
    margin: 0 auto;
}

.g-remove-check-code .g-remove-check-code_content input {
    width: 50px;
    height: 50px;
    font-size: 36px;
    text-align: center;
    border: none;
    outline: none;
    border: solid 1px rgba(187, 187, 187, 100);
    border-radius: 4px;
    -moz-appearance: textfield;
}

.g-remove-check-code .g-remove-check-code_content input.g-code-input_color {
    border-color: #5290FF;
}

.g-remove-check-code .g-remove-check-code_content input::-webkit-outer-spin-button,
.g-remove-check-code .g-remove-check-code_content input::-webkit-inner-spin-button {
    appearance: none;
    margin: 0;
}

.g-remove-check-code .g-remove-check-code_tip {
    font-size: 14px;
    color: #999;
    text-align: center;
}
</style>

效果展示
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

虚拟游戏理财 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 在一款虚拟游戏中生活,你必须进行投资以增强在虚拟游戏中的资产以免被淘汰出局。 现有一家Bank,它提供有若干理财产品m,风险及投资回报不同,你有N (元)进行投资,能接受的总风,险值为X。 你要在可接…

CVE-2019-5782:kArgumentsLengthType 设置偏小导致优化阶段可以错误的去除 CheckBound 节点

文章目录 环境搭建漏洞分析笔者初分析笔者再分析漏洞触发源码分析 漏洞利用总结 环境搭建 sudo apt install pythongit reset --hard b474b3102bd4a95eafcdb68e0e44656046132bc9 export DEPOT_TOOLS_UPDATE0 gclient sync -D// debug version tools/dev/v8gen.py x64.debug ni…

【ESP32 IDF】ESPTIMER定时器

文章目录 前言一、ESPTIMER定时器的介绍1.1 定时器是什么1.2 ESPTIMER定时器的介绍 二、ESPTIMER的使用2.1 简单使用过程2.2 停止定时器2.3 删除定时器 三、示例代码总结 前言 在ESP32 IDF开发框架中&#xff0c;ESPTIMER是一个功能强大的定时器模块&#xff0c;用于实现定时任…

Java八股文(RabbitMQ)

Java八股文のRabbitMQ RabbitMQ RabbitMQ RabbitMQ 是什么&#xff1f;它解决了哪些问题&#xff1f; RabbitMQ 是一个开源的消息代理中间件&#xff0c;用于在应用程序之间进行可靠的异步消息传递。 它解决了应用程序间解耦、消息传递、负载均衡、故障恢复等问题。 RabbitMQ …

JavaSE(上)-Day6

JavaSE&#xff08;上&#xff09;-Day6 数组数组的定义数组的初始化打印数组分析数组索引数组内存图 方法方法的定义和调用方法的重载方法的内存图 二维数组二位数组的创建和初始化二维数组的内存图 数组 1.数组是一种容器&#xff0c;可以一次存储多个相同类型的数据 数组的…

基于openresty构建运维工具链实践

本文字数&#xff1a;4591字 预计阅读时间&#xff1a;25 01 导读 如今OpenResty已广泛被各个互联网公司在实际生产环境中应用&#xff0c;在保留Nginx高并发、高稳定等特性基础上&#xff0c;通过嵌入Lua来提升在负载均衡层的开发效率并保证其高性能。本文主要介绍接口鉴权、流…

从零开始写 Docker(六)---实现 mydocker run -v 支持数据卷挂载

本文为从零开始写 Docker 系列第六篇&#xff0c;实现类似 docker -v 的功能&#xff0c;通过挂载数据卷将容器中部分数据持久化到宿主机。 完整代码见&#xff1a;https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识&#xff1a; …

搭建项目后台系统基础架构

任务描述 1、了解搭建民航后端框架 2、使用IDEA创建基于SpringBoot、MyBatis、MySQL、Redis的Java项目 3、以原项目为参照搭建项目所涉及到的各个业务和底层服务 4、以原项目为例&#xff0c;具体介绍各个目录情况并参照创建相关文件夹 1、创建项目后端 BigData-KongGuan …

【MySQL】MySQL视图

文章目录 一、视图的基本使用1.创建视图2.修改了视图&#xff0c;对基表数据有影响3.修改了基表&#xff0c;对视图有影响4.删除视图 二、视图规则和限制 一、视图的基本使用 视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称…

15届蓝桥杯备赛(2)

文章目录 刷题笔记(2)二分查找在排序数组中查找元素的第一个和最后一个位置寻找旋转排序数组中的最小值搜索旋转排序数组 链表反转链表反转链表II 二叉树相同的树对称二叉树平衡二叉树二叉树的右视图验证二叉搜索树二叉树的最近公共祖先二叉搜索树的最近公共祖先二叉树层序遍历…

管道(acwing,蓝桥杯,二分)

题目描述&#xff1a; 有一根长度为 len 的横向的管道&#xff0c;该管道按照单位长度分为 len 段&#xff0c;每一段的中央有一个可开关的阀门和一个检测水流的传感器。 一开始管道是空的&#xff0c;位于 Li的阀门会在 Si 时刻打开&#xff0c;并不断让水流入管道。 对于位…

WRF模型运行教程(ububtu系统)--III.运行WRF模型(官网案例)

零、创建DATA目录 # 1.创建一个DATA目录用于存放数据&#xff08;一般为fnl数据&#xff0c;放在Build_WRF目录下&#xff09;。 mkdir DATA # 2.进入 DATA cd DATA 一、WPS预处理 在模拟之前先确定模拟域&#xff08;即模拟范围&#xff09;,并进行数据预处理&#xff08…

我的尝试:Codigger + Vim

若您愿意耐心投入&#xff0c;学习 Vim 的过程其实远比想象中轻松。我对 Vim 产生兴趣&#xff0c;主要是源于它对提升生产力的巨大潜力。我尝试了 Neovim、NvChad 以及 Codigger Vim 插件&#xff0c;如今我的工作效率已远超从前。 那么&#xff0c;Vim 究竟是什么呢&#xff…

Leetcode 79. 单词搜索

心路历程&#xff1a; 做完这道题才发现是回溯&#xff0c;一开始想的是递归&#xff0c;判断完第i个字符后&#xff0c;只需要挨个判断第i1个字符在不在第i个字符的邻域。后来发现由于不能重复使用元素&#xff0c;所以需要维护一个visited列表&#xff0c;并且在遍历所有可能…

【进阶五】Python实现SDVRP(需求拆分)常见求解算法——自适应大邻域算法(ALNS)

基于python语言&#xff0c;采用经典自适应大邻域算法&#xff08;ALNS&#xff09;对 需求拆分车辆路径规划问题&#xff08;SDVRP&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整3. 求解结果4. 代码片段参考 往期优质资源 经过一年多的创作&#xff0c;目前…

Aigtek超声功率放大器产品介绍

超声功率放大器是一种特殊类型的功率放大器&#xff0c;专门用于增强和放大超声信号的功率。它在医疗、工业和科学领域中得到广泛应用。 一、超声功率放大器的基本概述 超声功率放大器是一种能够将低功率超声信号放大到更高功率水平的设备。它是超声系统的关键组成部分&#xf…

力扣1. 两数之和

思路&#xff1a;用一个map存放 已遍历过的元素和下标&#xff1b; 若当前元素是nums[i], 且该元素的另一半 target-nums[i] 在已遍历过的map里面&#xff0c;则返回两个元素的下标&#xff1b; class Solution {public int[] twoSum(int[] nums, int target) {int[] ans new…

腾讯云服务器多少钱1个月?2024一个月收费阿济格IE吧

2024腾讯云服务器多少钱一个月&#xff1f;5元1个月起&#xff0c;腾讯云轻量服务器4核16G12M带宽32元1个月、96元3个月&#xff0c;8核32G22M配置115元一个月、345元3个月&#xff0c;腾讯云轻量应用服务器61元一年折合5元一个月、4核8G12M配置646元15个月、2核4G5M服务器165元…

数据结构:详解【顺序表】的实现

1. 顺序表的定义 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储。动态顺序表与数组的本质区别是——根据需要动态的开辟空间大小。 2. 顺序表的功能 动态顺序表的功能一般有如下几个&#xff1a; 初始化顺序表打印顺序…

PlantUML Integration 编写短信服务类图

PlantUML Integration 写一个类图&#xff0c;主要功能为 1、编写一个serviceSms短信服务类&#xff1b; 2、需要用到短信的地方统一调用基建层的服务即可&#xff1b; 3、可以随意切换、增加短信厂商&#xff0c;不需要更改场景代码&#xff0c;只需要更改application.yml 里面…
最新文章