1、使用 span + input 标签实现
设计思路:
- 使用一个透明的 input 组件来接收验证码
- 利用 onkeyup 事件,将 input 中的数字写入到 span 中(span的个数和验证码的数量一致)
事件处理:
- 屏蔽input输入框的所有事件(这里是将input的高度置0),让用户点不到这个input
- 动态给span标签添加click事件,并且保证一组span中只能有一个持有click事件
效果如下:
代码实现:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
<style type="text/css">
body{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
div{
position: relative;
}
div span{
display: block;
float: left;
margin: 0 0.3125rem;
width: 2.1875rem;
height: 2.1875rem;
line-height: 2.1875rem;
border: 2px solid black;
text-align: center;
border-radius: 0.3125rem;
}
div>span:nth-child(1){
border-color: orange;
}
/* 将input隐藏起来 */
div input{
width: 0.0625rem;
height: 0;
line-height: 1.875rem;
font-size: 0.5rem;
position: absolute;
left: 0.3125rem;
opacity: 0;
/* 给他一个层级保证无法点到input */
z-index: -5;
}
</style>
</head>
<body>
<div>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<input type="number" oninput="if(value.length>6)value=value.slice(0,6)" checked="checked" onkeyup="showText(this.value)" autofocus="autofocus"/>
</div>
<script type="text/javascript">
window.onload=function(){
document.getElementsByTagName("span")[0].addEventListener("click",gotFocus)
}
function showText(value){
var cur = document.getElementsByTagName("span")[value.length];
var pre = document.getElementsByTagName("span")[value.length-1];
var next = document.getElementsByTagName("span")[value.length+1];
if(cur){
cur.innerHTML = "";
cur.style.borderColor = "orange";
cur.addEventListener("click",gotFocus);
}
if(pre){
pre.innerHTML = value.charAt(value.length-1);
pre.style.borderColor = "black";
pre.removeEventListener("click",gotFocus);
}
if(next){
next.innerHTML = "";
next.style.borderColor = "black";
next.removeEventListener("click",gotFocus);
}
}
function gotFocus(e){
e.stopPropagation();
document.getElementsByTagName("input")[0].focus();
}
</script>
</body>
</html>
注:不可以直接复制验证码粘贴,可以通过修改showText的逻辑来实现复制粘贴验证码
2、使用多个 input 标签实现
设计思路:
- 根据需要选择多个input标签存放验证码的每一位数字,需要获取多个输入框的数字拼接为最终验证码。
事件处理:
- 一组input保证只有0个或1个input能够获得焦点
- 获得焦点的input的value一定为空
- 根据是否点击删除(keyCode为8)按钮,来确定光标移动方向
效果演示:
代码实现:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
<style type="text/css">
body{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* 每一个input输入框的样式 */
div input{
width: 2.375rem;
height: 2.375rem;
line-height: 2.375rem;
text-align: center;
background-color: #eeeeee;
margin: 0 0.3125rem;
border-radius: 0.625rem;
border: none;
}
div input:focus{
/* 去掉input框获得焦点时的外边框 */
outline: none;
}
</style>
</head>
<body>
<div>
<!-- number保证输入框获取焦点,拉起的是数字键盘 -->
<!-- oninput保证输入的是纯数字 -->
<!-- autofocus设置第一个input自动获得焦点 -->
<input type="number" oninput="value=value.replace(/[^\d]/g,'')" onkeyup="moveCursor()" autofocus="autofocus"/>
<input type="number" oninput="value=value.replace(/[^\d]/g,'')" onkeyup="moveCursor()">
<input type="number" oninput="value=value.replace(/[^\d]/g,'')" onkeyup="moveCursor()">
<input type="number" oninput="value=value.replace(/[^\d]/g,'')" onkeyup="moveCursor()">
<input type="number" oninput="value=value.replace(/[^\d]/g,'')" onkeyup="moveCursor()">
<input type="number" oninput="value=value.replace(/[^\d]/g,'')" onkeyup="moveCursor()">
</div>
<script type="text/javascript">
var index = 0; //标识哪一个input框获得焦点(光标),获得焦点的input框value值为空
var key;
// 获取用户每一次点击键盘的按键值 => 按键值为8时为删除键
document.onkeydown=function(event){
key = event.keyCode;
};
window.onload=function(){
// 除了第一个input,其他input无法获取焦点
var arr = document.getElementsByTagName("input");
for(var i = 1; i < arr.length; i++){
arr[i].addEventListener("focus",forbidFoucs);
}
};
function moveCursor(){
var pre = document.getElementsByTagName("input")[index];
if(key != 8 && pre.value.length != 0){
// 若用户点击的是删除键,或者其他非数字按键(非数字按键不会改变input输入框中的value)=> input的焦点需要后移,同时让前一个input无法获取焦点
pre.addEventListener("focus",forbidFoucs)
if(index < 5) {
// 光标最远只能移动到最后一个input,也就是 index 为 5 指向的input
var obj = document.getElementsByTagName("input")[++index];
obj.removeEventListener("focus",forbidFoucs);
obj.focus();
}else{
// 当 index 走到 6 时,就需要让最后一个input失去焦点
pre.blur();
/**
* 此处写业务逻辑代码………………………………
*/
}
}else{
pre.addEventListener("focus",forbidFoucs);
if(index > 0){
// 当用户点击删除按钮的时候,需要删除前一个input中的内容,并将光标前移(限制光标不可跑飞)
var obj = document.getElementsByTagName("input")[--index];
obj.removeEventListener("focus",forbidFoucs);
obj.value = "";
obj.focus();
}
}
}
// 禁止用户通过点击获取input的焦点
function forbidFoucs(){
console.log(this)
this.blur();
}
</script>
</body>
</html>
注:所有代码在Android手机上已完成测试。