基于react封装验证码、密码输入框组件。

项目场景:

最近有一个H5需求是需要核销验证码,因为antd-mobile的版本过低(最新版本有),别的组件没有这个功能,自己封装了一个,这里记录一下,效果图如下在这里插入图片描述


使用:

如果想要直接给input赋值,可以使用通过useImperativeHandle暴漏出来的 changeInput事件 codeInputRef&&codeInputRef.current.changeInput(“1234”);

const getCodeNum = useCallback((num) => {
    //num 就是组件反回来的值
    setCode(num);
  }, []);

 <PasscodeInput onChange={getCodeNum} ref={codeInputRef} />
 

代码如下:

PasscodeInput 组件

import React, {
  memo,
  useImperativeHandle,
  forwardRef,
  useState,
  useRef,
  useCallback,
} from "react";
import styles from "./PasscodeInput.less";

export default memo(
  forwardRef(({ onChange }, ref) => {
    const inputRef = useRef(null);
    const fieldList = useRef(null);
    const [inputVal, setInputVal] = useState("");

    useImperativeHandle(ref, () => {
      return {
        changeInput: (val) => {
          changeHandle({
            target: {
              value: val,
            },
          });
        },
      };
    });

    const calcCursorPosition = useCallback(() => {
      // 这里需要获取ref的value值,不然onchange的时候会有异步问题
      const length = inputRef.current.value.length;
      if (length < 4) {
        fieldList.current.children[length].classList.add(
          styles["field-item-focus"]
        );
      }
    }, [inputVal]);

    const removeCursor = useCallback(() => {
      let newArr = Array.from(fieldList.current.children);
      newArr.forEach((item) => {
        if (
          Array.from(item["classList"]).some((r) =>
            r.includes("field-item-focus")
          )
        ) {
          item.classList.remove(
            Array.from(item["classList"]).find((r) =>
              r.includes("field-item-focus")
            )
          );
        }
      });
    }, [inputVal]);

    const changeHandle = useCallback(
      (e) => {
        // 监听input输入事件,只支持输入数字,过滤非数字字符
        let v = e.target.value.replace(/[^\d]/g, "");

        v = v.length > 4 ? v.substr(0, 4) : v;
        // 这里需要改变inputRef.currnet的值,不然input的值会超出四位
        inputRef.current.value = v;
        onChange && onChange(v); //传递给父组件
        setInputVal(v);
        // 考虑粘贴情况,循环赋值
        // 移除旧光标
        removeCursor();
        // 计算新光标出现位置
        calcCursorPosition();
      },
      [inputVal]
    );

    const blurHandle = useCallback(() => {
      removeCursor();
    }, [inputVal]);

    const focusHandle = useCallback(() => {
      calcCursorPosition();
    }, [inputVal]);

    return (
      <div className={styles.inputBox}>
        <div className={styles["field-list"]} ref={fieldList}>
          <div className={styles["field-item"]}>{inputVal[0]}</div>
          <div className={styles["field-item"]}>{inputVal[1]}</div>
          <div className={styles["field-item"]}>{inputVal[2]}</div>
          <div className={styles["field-item"]}>{inputVal[3]}</div>
        </div>
        <input
          ref={inputRef}
          className={styles["field-input"]}
          onChange={changeHandle}
          onBlur={blurHandle}
          onFocus={focusHandle}
          type="text"
        />
      </div>
    );
  })
);

样式文件:

.inputBox {
  position: relative;
  width: 100%;
  overflow: hidden;
}
.field-list {
  padding: 0 31px;
  display: flex;
  justify-content: space-between;
}
.field-item {
  box-sizing: border-box;
  width: 120px;
  height: 130px;
  line-height: 130px;
  font-size: 78px;
  color: #363a44;
  text-align: center;
  font-weight: bold;
  border: 1px solid #e8e9ec;
  border-radius: 16px 16px 16px 16px;
}

.field-item-focus::before {
  content: "";
  display: block;
  width: 4px; 
  height: 65px;
  margin:32px auto;
  background: #428ffc;
  animation: blink 1s steps(1) infinite;
}
@keyframes blink {
  50% {
    opacity: 0;
  }
}
.field-input {
  box-sizing: border-box;
  position: absolute;
  top: 0;
  right: 0;

  width: 100%;
  height: 130px;
  padding: 0;
  border: none;
  outline: none;
  opacity: 0;
  background: transparent;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 React Swipeable 库来实现基于 React 的滑动图片验证码组件。该库提供了一个 Swipeable 组件,可以帮助你快速实现滑动操作。 下面是一个基本的滑动图片验证码组件的示例: ```jsx import React, { useState } from 'react'; import Swipeable from 'react-swipeable'; const SlideCaptcha = ({ onSuccess, onFailure }) => { const [isSliding, setIsSliding] = useState(false); const [sliderPosition, setSliderPosition] = useState(0); const [sliderWidth, setSliderWidth] = useState(0); const handleSwipeStart = () => { setIsSliding(true); }; const handleSwipeMove = (event, deltaX) => { if (!isSliding) return; const newSliderPosition = Math.max(0, Math.min(sliderWidth, sliderPosition + deltaX)); setSliderPosition(newSliderPosition); }; const handleSwipeEnd = () => { setIsSliding(false); if (sliderPosition >= sliderWidth * 0.9) { onSuccess(); } else { onFailure(); setSliderPosition(0); } }; const handleSliderRef = (node) => { if (node) { setSliderWidth(node.offsetWidth); } }; return ( <div> <div className="captcha-image" /> <Swipeable className="slider" onSwiping={handleSwipeMove} onSwipingStart={handleSwipeStart} onSwipingEnd={handleSwipeEnd} > <div className="slider-inner" ref={handleSliderRef}> <div className="slider-handle" style={{ left: sliderPosition }} /> </div> </Swipeable> </div> ); }; export default SlideCaptcha; ``` 在这个示例中,我们使用 Swipeable 组件来监听滑动事件,并根据滑动距离来移动滑块的位置。当滑块移动到指定位置时,触发 onSuccess 回调函数。如果滑块没有移动到指定位置,将调用 onFailure 回调函数并将滑块重置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值