基于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样式


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


相关文章
|
1月前
|
移动开发 前端开发 UED
React 音频预览组件 Audio Preview
在现代Web开发中,React框架下的音频播放功能日益重要。本文介绍如何使用React创建交互式音频预览组件,涵盖基础构建、常见问题及解决方案。通过HTML5音频标签实现基本播放控制,使用状态管理增强功能。解决跨域资源共享(CORS)、格式兼容性、自动播放限制等问题,并探讨性能优化、样式定制、事件处理、移动端适配、错误处理、国际化支持及组件集成等关键点,帮助开发者提升组件稳定性和用户体验。
40 10
|
1月前
|
移动开发 前端开发 API
React 音频播放器组件 Audio Player
本文介绍如何使用React创建音频播放器组件,涵盖核心功能如播放/暂停、进度条、音量控制和时间显示。通过HTML5 `&lt;audio&gt;` 元素和React的声明式状态管理,实现交互式音频播放。常见问题包括控件不响应、进度条无法更新和音量控制失灵,并提供解决方案。此外,还讨论了浏览器兼容性、异步错误处理和性能优化等易错点及避免方法。
357 123
|
22天前
|
前端开发 JavaScript
除了使用Route组件,React Router还有其他方式处理404错误页面吗
除了使用Route组件,React Router还有其他方式处理404错误页面吗
82 58
|
22天前
|
前端开发
React 中高阶组件的原理是什么?
React 中高阶组件的原理是什么?
90 57
|
22天前
|
前端开发 开发者
除了函数组件和类组件,React 还有其他创建组件的方式吗?
除了函数组件和类组件,React 还有其他创建组件的方式吗?
80 57
|
22天前
|
前端开发
如何在React Router中定义404错误页面组件?
如何在React Router中定义404错误页面组件?
76 57
|
22天前
|
前端开发
在 React 中使用高阶组件时,如何避免命名冲突?
在 React 中使用高阶组件时,如何避免命名冲突?
81 56
|
2月前
|
存储 编解码 前端开发
React 视频上传组件 Video Upload
随着互联网的发展,视频内容在网站和应用中愈发重要。本文探讨如何使用React构建高效、可靠的视频上传组件,涵盖基础概念、常见问题及解决方案。通过React的虚拟DOM和组件化开发模式,实现文件选择、进度显示、格式验证等功能,并解决跨域请求、并发上传等易错点。提供完整代码案例,确保用户能顺畅上传视频。
146 92
|
16天前
|
移动开发 前端开发 JavaScript
React音频播放列表组件:常见问题、易错点与解决方案
本文介绍了在React中实现音频播放列表时常见的挑战及解决方案。通过基础实现、常见问题分析和最佳实践,帮助开发者避免状态管理、生命周期控制和事件处理中的陷阱。关键点包括使用`useRef`操作音频元素、`useState`同步播放状态、全局状态管理防止多音频同时播放、以及通过`useEffect`清理资源。还提供了代码示例和跨浏览器兼容性处理方法,确保高效实现功能并减少调试时间。
80 30
|
13天前
|
编解码 前端开发 开发者
React 图片组件样式自定义:常见问题与解决方案
在 React 开发中,图片组件的样式自定义常因细节问题导致布局错乱、性能损耗或交互异常。本文系统梳理常见问题及解决方案,涵盖基础样式应用、响应式设计、加载状态与性能优化等,结合代码案例帮助开发者高效实现图片组件的样式控制。重点解决图片尺寸不匹配、边框阴影不一致、移动端显示模糊、加载失败处理及懒加载等问题,并总结易错点和最佳实践,助力开发者提升开发效率和用户体验。
42 22