稀土掘金 稀土掘金

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

1、效果图

最终实现效果:

1

2、实现过程
第一版本
<Flex className="login-code">
    <Flex.Item>
        <InputItem
            type="number"
            className="input1"
            maxLength={1}
            value={codearr[0]}
            onChange={value => {
                console.log("onChange", value)
                codearr[0] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 1)();
            }}
        />
    </Flex.Item>
    <Flex.Item>
        <InputItem
            type="number"
            className="input2"
            maxLength={1}
            value={codearr[1]}
            onChange={value => {
                codearr[1] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 2)();
            }}
        />
    </Flex.Item>
    <Flex.Item>
        <InputItem
            type="number"
            className="input3"
            maxLength={1}
            value={codearr[2]}
            onChange={value => {
                codearr[2] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 3)();
            }}
        />
    </Flex.Item>
    <Flex.Item>
        <InputItem
            type="number"
            className="input4"
            maxLength={1}
            value={codearr[3]}
            onChange={value => {
                codearr[3] = value;
                this.dispatch({ type: "input", data: { codearr: codearr, random: Math.random() } });
                this.moveNext.bind(this, value, 4)();
            }}
        />
    </Flex.Item>
</Flex>
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<P extends IProps = IProps, S extends IState = IState> extends ViewComponent.Base<P, S> {
        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 (
                <>
                    <div className="header-bodernone">{super.renderHeader()}</div>
                </>
            );
        }
        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 (
                <>
                    <WingBlank>
                        <div className="login-title">输入手机验证码</div>
                        <div className="keyboard-input">
                            <input
                                type="tel"
                                ref={(e) => 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)
                                    }
                                }}
                            />
                            <div className="keyboard-span">
                                <span />
                                <span />
                                <span />
                                <span />
                            </div>
                        </div>
                        <div className="input-yzm-box" onClick={() => {
                            this.inputRef.focus()
                        }}><span id="cursorspan1">{codestr && codestr.slice(0, 1)}</span>
                            <span id="cursorspan2">{codestr && codestr.slice(1, 2)}</span>
                            <span id="cursorspan3">{codestr && codestr.slice(2, 3)}</span>
                            <span id="cursorspan4">{codestr && codestr.slice(3, 4)}</span></div>
                        <Countdownauto start={this.sendVerifyCode.bind(this)} content="获取验证码" />
                    </WingBlank>
                </>
            );
        }
    }

    export const Page = template(Component, state => state[Namespaces.login]);
}


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

哆哆女性网月影天殇解个梦关键词优化SEO奥比岛名字棋牌室起名字大全集寻找梵米尔的画笔与颜料石头网站 广告设计姓温的怎么起名电影天堂免费电影网站个人制作流程森算seo优化幼儿园如何起名bazaar艺术珠宝晚字女孩起名明星孩子生辰八字五行起名公司起名大全2个字免费属猪的小朋友起名宜用字武汉seo培训潘氏女孩高分取名起名大全大全取名字懂周易的制作企业企业网站起公司名字大全免费梦见西瓜周公解梦贷款公司起名日剧美丽的他原著小说带恒的公司起名起名字庆奈曼旗电话大全不负此生观后感周公解梦梦见大便拉在身上淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻不负春光新的一天从800个哈欠开始有个姐真把千机伞做出来了国产伟哥去年销售近13亿充个话费竟沦为间接洗钱工具重庆警方辟谣“男子杀人焚尸”男子给前妻转账 现任妻子起诉要回春分繁花正当时呼北高速交通事故已致14人死亡杨洋拄拐现身医院月嫂回应掌掴婴儿是在赶虫子男孩疑遭霸凌 家长讨说法被踢出群因自嘲式简历走红的教授更新简介网友建议重庆地铁不准乘客携带菜筐清明节放假3天调休1天郑州一火锅店爆改成麻辣烫店19岁小伙救下5人后溺亡 多方发声两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#青海通报栏杆断裂小学生跌落住进ICU代拍被何赛飞拿着魔杖追着打315晚会后胖东来又人满为患了当地回应沈阳致3死车祸车主疑毒驾武汉大学樱花即将进入盛花期张立群任西安交通大学校长为江西彩礼“减负”的“试婚人”网友洛杉矶偶遇贾玲倪萍分享减重40斤方法男孩8年未见母亲被告知被遗忘小米汽车超级工厂正式揭幕周杰伦一审败诉网易特朗普谈“凯特王妃P图照”考生莫言也上北大硕士复试名单了妈妈回应孩子在校撞护栏坠楼恒大被罚41.75亿到底怎么缴男子持台球杆殴打2名女店员被抓校方回应护栏损坏小学生课间坠楼外国人感慨凌晨的中国很安全火箭最近9战8胜1负王树国3次鞠躬告别西交大师生房客欠租失踪 房东直发愁萧美琴窜访捷克 外交部回应山西省委原副书记商黎光被逮捕阿根廷将发行1万与2万面值的纸币英国王室又一合照被质疑P图男子被猫抓伤后确诊“猫抓病”

哆哆女性网 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化