You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Material UI中实现粘贴数字自动拆分填充到多个独立文本框

React + Material UI 实现OTP粘贴自动拆分填充方案

核心实现逻辑

  • 监听输入框的paste粘贴事件,拦截默认粘贴行为
  • 过滤粘贴内容中的非数字字符,按长度拆分填充到对应输入框
  • 填充完成后自动调整焦点位置

具体修改步骤

1. 定义粘贴事件处理函数

在组件内部新增handlePaste方法,处理剪贴板内容的读取、过滤、拆分逻辑:

const handlePaste = (e: React.ClipboardEvent, index: number) => {
  // 阻止默认粘贴,避免整串内容直接填入当前输入框
  e.preventDefault();
  // 获取剪贴板文本内容
  const pastedText = e.clipboardData.getData('text');
  // 过滤所有非数字字符,只保留数字
  const pureNumbers = pastedText.replace(/[^0-9]/g, '');
  if (!pureNumbers) return;

  const newOtpArr = [...otpArr];
  // 从当前触发粘贴的输入框位置开始填充
  for (let i = 0; i < pureNumbers.length; i++) {
    const targetIndex = index + i;
    // 超出OTP总长度就停止填充
    if (targetIndex >= otpArr.length) break;
    newOtpArr[targetIndex] = pureNumbers[i];
  }
  setOtpArr(newOtpArr);

  // 填充完成后自动跳转到最后一个填充位置的下一个输入框
  const lastFilledIndex = Math.min(index + pureNumbers.length - 1, otpArr.length - 1);
  if (lastFilledIndex < otpArr.length - 1) {
    inputRefs.current[lastFilledIndex + 1]?.current?.focus();
  }
};

2. 修正输入框Ref类型

原代码中Ref声明为HTMLDivElement类型,不符合TextField inputRef指向原生输入框的实际类型,调整为:

const inputRefs = useRef([
  React.createRef<HTMLInputElement>(),
  React.createRef<HTMLInputElement>(),
  React.createRef<HTMLInputElement>(),
  React.createRef<HTMLInputElement>(),
  React.createRef<HTMLInputElement>(),
  React.createRef<HTMLInputElement>()
])

3. 绑定粘贴事件到输入框

给每个NumberTextField新增onPaste属性绑定处理函数即可。

完整修改后代码

const [otpArr, setOtpArr] = useState<string[]>(['', '', '', '', '', ''])
const inputRefs = useRef([
  React.createRef<HTMLInputElement>(), 
  React.createRef<HTMLInputElement>(), 
  React.createRef<HTMLInputElement>(), 
  React.createRef<HTMLInputElement>(), 
  React.createRef<HTMLInputElement>(), 
  React.createRef<HTMLInputElement>()
])

const handlePaste = (e: React.ClipboardEvent, index: number) => {
  e.preventDefault();
  const pastedText = e.clipboardData.getData('text');
  const pureNumbers = pastedText.replace(/[^0-9]/g, '');
  if (!pureNumbers) return;

  const newOtpArr = [...otpArr];
  for (let i = 0; i < pureNumbers.length; i++) {
    const targetIndex = index + i;
    if (targetIndex >= otpArr.length) break;
    newOtpArr[targetIndex] = pureNumbers[i];
  }
  setOtpArr(newOtpArr);

  const lastFilledIndex = Math.min(index + pureNumbers.length - 1, otpArr.length - 1);
  if (lastFilledIndex < otpArr.length - 1) {
    inputRefs.current[lastFilledIndex + 1]?.current?.focus();
  }
};

// 渲染部分
{otpArr.map((x, index) => (
  <NumberTextField
    inputRef={inputRefs.current[index]}
    variant='outlined'
    size='small'
    id={`otp-${index}`}
    value={x}
    key={index}
    onChange={(e: any) => {
      const temp = [...otpArr]
      temp[index] = e.target.value
      setOtpArr(temp)
      if ((index < otpArr.length - 1) && e.target.value.length === 1) {
        inputRefs.current[index + 1]?.current?.focus()
      }
    }}
    onPaste={(e) => handlePaste(e, index)}
    inputProps={{ maxLength: 1 }}
    style={{
      width: '3rem',
      direction: 'ltr',
      marginTop: '3rem',
      marginRight: '0.5rem'
    }}
  />
))}

额外优化建议

可以新增退格键跳转逻辑:当输入框内容为空时按下退格键,自动聚焦到上一个输入框,优化手动输入体验。

内容的提问来源于stack exchange,提问作者Banafshe Alipour

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:06:02