基于React Hooks封装的验证码组件

简介: 基于React Hooks封装的验证码组件

一、概述


现在项目中一般涉及到用户登录都支持了手机验证码登录,本篇文章就是给大家分享一下胡哥封装的一个验证码组件rc-codebox,采用的是React Hooks的方式来开发的。


二、验证码组件介绍与安装


rc-codebox是基于react hooks的验证码组件,支持特性如下:


API


Name Description Type Default
len 验证码的位数 number 6
onChange 验证码改变时的callback (code: string) => void --
className 自定义类名 string --
autoFocus 是否自动获取焦点 boolean true


安装:


yarn add rc-codebox


使用:


import React, { useState } from 'react';
import { CodeBox } from 'rc-codebox';
export default () => {
  // 初始化code变量,接收验证码
  const [code, setCode] = useState('');
  /**
   * @method onChange
   * @description 检测用户输入的验证码
   */
  const onChange = (code) => {
    setCode(code);
  };
  return (
    <div>
      <h3>现在输入的code是:{code}</h3>
      {/* 渲染codeBox,指定验证码长度,自动获取焦点,检测用户输入验证码时的onChange事件 */}
      <CodeBox len={6} onChange={onChange} autoFocus={true}></CodeBox>
    </div>
  );
};


三、验证码组件设计与开发


rc-codebox验证码组件是基于组件开发工具dumi开发的。


在这里必须给dumi吹一波,dumi-为组件开发场景而生的文档工具,有几个非常优秀的特点:


  1. API文档自动生成,这个功能个人感觉太棒了,直接根据组件内部注释、TypeScript类型描述自动生成API文档,始终保持如一。免去了开发完组件还得写文档的烦恼,对程序员简直不要太好~


  1. 丰富的Markdown扩展,可以方便的渲染组件demo,支持文档编写、管理,主题可以定制多个


搭建组件项目:


# 初始化一个站点模式的组件库开发脚手架 - 当将项目推送到github时可以使用相关配置生成一个站点
yarn create @umijs/dumi-lib --site


验证码组件开发


import React, { useRef, useEffect } from 'react';
import './index.less';
interface CodeBoxProps {
  /**
   * @description 验证码的位数
   * @default 6
   */
  len?: number;
  /**
   * @description 验证码改变时的callback
   */
  onChange?: (code: string) => void;
  /**
   * @description 自定义类名
   *
   */
  className?: string;
  /**
   * @description 是否自动获取焦点
   * @default true
   */
  autoFocus?: boolean;
}
export function CodeBox(props: CodeBoxProps) {
  // 配置相关默认值
  const { len = 6, onChange, className = '', autoFocus = true } = props;
  // 输入框数组
  const inputArr = new Array(len).fill('');
  // 输入框ref
  const inputRefs = useRef<any>([]);
  /**
   * @method getRef
   * @description 获取input的ref
   */
  const getRef = (dom: any) => {
    if (inputRefs?.current?.length === len) {
      return;
    }
    inputRefs.current.push(dom);
  };
  /**
   * @method onInputKeyDown
   * @method 处理input的删除事件
   * @param e 事件
   * @param index number input输入框对应的索引
   */
  const onInputKeyDown = (e: any, index: number) => {
    switch (e.key) {
      case 'Backspace':
        if (index > 0 && !e.target.value) {
          const currentInputRef = inputRefs.current[index];
          currentInputRef.value = '';
          const prevInputRef = inputRefs.current[index - 1];
          prevInputRef.focus();
          // prevInputRef.select();
          e.preventDefault();
        }
        break;
    }
  };
  /**
   * @method onInputValueChange
   * @description 当输入的验证码发生变化时
   * @param index number input输入框对应的索引
   */
  const onInputValueChange = (index: number, e: any) => {
    let code = '';
    inputRefs.current?.forEach((ref: any) => {
      if (ref?.value) {
        code += ref?.value;
      } else {
        code += ' ';
      }
    });
    // 判断是删除操作
    if (index > 0 && !e.target.value) {
      const prevInputRef = inputRefs.current[index - 1];
      prevInputRef.focus();
    }
    // 判断是写入操作
    if (index < len - 1 && e.target.value) {
      const nextInputRef = inputRefs.current[index + 1];
      nextInputRef.focus();
    }
    onChange && onChange(code);
  };
  /**
   * @method getInputClassName
   * @description 动态获取每个验证码输入框的类名,增加已输入码的输入框样式
   * @param index number 索引
   * @returns string
   */
  const getInputClassName = (index: number) => {
    const currentInputRef = inputRefs.current[index];
    const value = currentInputRef?.value;
    const defaultClassName = 'code-box-input';
    return value ? defaultClassName + ' has-string' : defaultClassName;
  };
  useEffect(() => {
    // 自动获取焦点的处理
    if (autoFocus) {
      inputRefs?.current[0].focus();
    }
  }, [autoFocus]);
  return (
    <div className={className ? `code-box ${className}` : 'code-box'}>
      {/* 渲染每一个验证码输入框 */}
      {inputArr.map((v, index) => {
        return (
          <input
            ref={getRef}
            maxLength={1}
            className={getInputClassName(index)}
            key={index}
            type="text"
            onFocus={() => {
              inputRefs.current[index].select();
            }}
            onKeyDown={(e) => {
              onInputKeyDown(e, index);
            }}
            onChange={(e) => {
              onInputValueChange(index, e);
            }}
          />
        );
      })}
    </div>
  );
}
export default CodeBox;


index.less文件


.code-box {
  display: flex;
  flex-direction: row;
  &-input {
    width: 30px;
    margin-right: 10px;
    color: #333;
    font-size: 36px;
    text-align: center;
    border: none;
    border-bottom: 2px solid #ccc;
    outline: none;
    &.has-string {
      border-color: #575866;
    }
  }
}


这里是less样式


具体效果可以点击这里的传送门查看效果!


相关文章
|
2天前
|
前端开发 测试技术 开发工具
探索前端框架React Hooks的优势与应用
本文将深入探讨前端框架React Hooks的优势与应用。通过分析React Hooks的特性以及实际应用案例,帮助读者更好地理解和运用这一现代化的前端开发工具。
|
2天前
|
前端开发 JavaScript
react常用的hooks有哪些?
react常用的hooks有哪些?
15 0
|
2天前
|
前端开发 JavaScript UED
使用React Hooks优化前端应用性能
本文将深入探讨如何使用React Hooks来优化前端应用的性能,重点介绍Hooks在状态管理、副作用处理和组件逻辑复用方面的应用。通过本文的指导,读者将了解到如何利用React Hooks提升前端应用的响应速度和用户体验。
|
20小时前
|
前端开发 JavaScript
React Hooks:让你轻松掌握函数组件的状态与管理
React Hooks:让你轻松掌握函数组件的状态与管理
|
2天前
|
缓存 前端开发
Web开发:深入探讨React Hooks的使用和最佳实践
Web开发:深入探讨React Hooks的使用和最佳实践
10 0
|
2天前
|
存储 前端开发 JavaScript
React Hooks实战:从useState到useContext深度解析
React Hooks 深度解析:useState用于函数组件的状态管理,通过初始化和更新状态实现渲染控制;useContext则提供跨组件数据传递。useState的状态更新是异步的,不支持浅比较,可结合useEffect处理副作用。useContext在多层组件间共享状态,但可能导致不必要的渲染。两者结合可创建复杂应用场景,如带主题切换的计数器。了解其工作原理和优化策略,能有效提升React应用性能。
|
2天前
|
前端开发 API 开发者
React Hooks API:自定义Hooks的创建与使用
【4月更文挑战第25天】本文介绍了React自定义Hooks的创建与使用。自定义Hooks是提升React开发效率的关键工具。
|
2天前
|
前端开发
探索React Hooks:一种全新的组件逻辑管理方式
React Hooks是React 16.8版本引入的一项新功能,它改变了我们编写React组件的方式。本文将从Hooks的起源讲起,逐步分析Hooks的优势,并通过具体示例展示Hooks在组件逻辑管理中的应用,旨在帮助读者更好地理解和运用React Hooks。
|
2天前
|
前端开发 JavaScript
使用React Hooks实现简单的计数器应用
使用React Hooks实现简单的计数器应用
|
2天前
|
前端开发 JavaScript
【边做边学】React Hooks (二)——useEffect Hook
【边做边学】React Hooks (二)——useEffect Hook