H5实现4位验证码输入框思路

1、效果图

最终实现效果:
H5实现4位验证码输入框思路_第1张图片

2、实现过程
第一版本

    
         {
                console.log("onChange", value)
                codearr[0] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 1)();
            }}
        />
    
    
         {
                codearr[1] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 2)();
            }}
        />
    
    
         {
                codearr[2] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 3)();
            }}
        />
    
    
         {
                codearr[3] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 4)();
            }}
        />
    

moveNext(value, index) {
    console.log(value, value.length)
    if (value && value.length) {
        setTimeout(() => { // 解决iOS不能自动跳转
            $(`.input${index + 1} input`).focus();
        })
        this.checkSend();
    } else {
        setTimeout(() => { // 解决iOS不能自动跳转
            $(`.input${index - 1} input`).focus();
        })
    }
}

大致思路是创建四个input,输入后跳转下一个input中并主动聚焦输入框.

缺点:删除时不能做到流畅退格删除

第二版本
  .key-input {
    width: 100%;
    height: 50px;
    line-height: 50px;
    padding: 0 4px;
    letter-spacing: 49px;
    box-sizing: border-box;
    text-indent: 21px;
    appearance: none;
    border: transparent;
    font-size: 18px;
    color: transparent;
    text-shadow: 0 0 0 #02b8cd;
  }

使用一个输入框,限制输入框输入长度为4并使用样式调整字体间间距模拟类似输入框

缺点: 当输入至第4位后光标会继续往下跳只是不能输入,无法主动控制光标不跳转,后面想着第四位后主动取消input聚焦输入,依然会出现光标引起的样式问题.

第三版本
import React from "react";

import { Toast, WingBlank } from "antd-mobile";

import { template, ViewComponent, Validators, setEventWithLabel } from "@reco-mobile/core";
import { Namespaces } from "@reco-mobile/auth-models";

import { statisticsEvent } from "@reco-mobile/statistics";

import { Countdownauto } from "./countdownauto"

export namespace Code {
    export interface IProps extends ViewComponent.IProps { }

    export interface IState extends ViewComponent.IState {
        viewRef?: any;
    }

    export class Component

extends ViewComponent.Base { showloading = true; namespace = Namespaces.login; showloadingContent = "登录中"; inputRef; componentWillUnmount() { this.dispatch({ type: "input", data: { codestr: null } }); } componentDidMount() { this.dispatch({ type: "hideLoading" }); this.inputRef.focus() } tranformClass(index) { for (let i = 0; i < 4; i++) { if (i + 1 === index) { $(`#cursorspan${i + 1}`).addClass("cursorspan"); } else { $(`#cursorspan${i + 1}`).removeClass("cursorspan"); } } } renderHeader(): JSX.Element | null { return ( <>

{super.renderHeader()}
); } loginNameValidator() { const { cellphone, required, composeControl } = Validators, { state } = this.props; return composeControl([required, cellphone], { value: state!.get("loginName"), name: "手机号码" }); } validator() { const { required, maxLength, minLength, composeControl, ValidatorControl } = Validators, { state } = this.props; return ValidatorControl( this.loginNameValidator(), composeControl([required, maxLength(4), minLength(4)], { value: state!.get("password"), name: "验证码" }) ); } login() { const msg = this.validator()!(); if (msg) { Toast.fail(msg.join(), 1); return; } this.dispatch({ type: "input", data: { loading: true } }); this.dispatch({ type: "submit", error: e => Toast.fail(e.errmsg), callback: () => { Toast.success("登录成功", 1); } }); setEventWithLabel(statisticsEvent.c_app_Myself_verificationCodeLogin); // 验证码登录 } sendVerifyCode(delay: Function) { const { state } = this.props; this.dispatch({ type: "sendVerifyCode", data: { username: state!.get("loginName") }, delay }); } checkSend(codestr) { if (codestr && codestr.length === 4) { this.dispatch({ type: "input", data: { password: codestr } }); setTimeout(() => { this.login(); }); } } renderBody(): JSX.Element | null { const { state } = this.props, codestr = state!.get("codestr"); return ( <>
输入手机验证码
this.inputRef = e} // className="key-input" onTouchMove={e => { e.preventDefault(); }} maxLength={4} onChange={(event) => { let value = event.target.value; // alert(value); // console.log(value); this.dispatch({ type: "input", data: { codestr: value } }); this.checkSend(value); if (value.length + 1 > 4) { this.tranformClass(value.length) } else { this.tranformClass(value.length + 1) } }} onBlur={() => { this.tranformClass(5) }} onFocus={() => { if (codestr) { if (codestr.length + 1 > 4) { this.tranformClass(codestr.length) } else { this.tranformClass(codestr.length + 1) } } else { this.tranformClass(1) } }} />
{ this.inputRef.focus() }}>{codestr && codestr.slice(0, 1)} {codestr && codestr.slice(1, 2)} {codestr && codestr.slice(2, 3)} {codestr && codestr.slice(3, 4)}
); } } export const Page = template(Component, state => state[Namespaces.login]); }

创建一个input和四个div,隐藏input不可见主动聚焦可输入,四个div分别映射input四位输入数字,光标闪烁也是四个div通过样式动画模拟出来的,最终完美解决.

你可能感兴趣的:(我的前端)