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

React+RHF+MUI下自定义输入掩码添加可编辑字符串求助

自定义掩码输入框解决方案

技术栈

  • Js + React
  • React Hook Form
  • Material UI

需求目标

需要实现一个带自定义掩码的输入框,掩码结构为:

  • 固定前缀 vm-
  • 用户可编辑的字符串(位于vm-之后、tenant变量之前)
  • 来自其他输入框的动态变量tenant(通过watch('tenant')获取)
  • 三位用户可编辑的整数

问题

目前自行实现了掩码逻辑,但无法将代码中固定的a替换为用户可编辑的字符串,该字符串需要放在vm-和tenant变量之间。

现有代码

import React, { useEffect } from 'react';
import { Box, TextField, Typography } from '@mui/material';
import { Controller } from 'react-hook-form';

export const Name = ({ fieldArrayName, index, setValue, watch, control }) => {
  const tenant = watch('tenant');

  useEffect(() => {
    if (tenant) setValue(`${fieldArrayName}.${index}.name`, '');
  }, [tenant]);

  const formatInputValue = (tenant, input) => {
    const tenantFormatted = tenant ? `vm-a${tenant}-` : 'vm-a';
    const inputFormatted = input.slice(tenantFormatted.length);
    return `${tenantFormatted}${inputFormatted.replace(/\D/g, '').slice(0, 3)}`;
  };

  return (
    <>
      <Box>
        <Controller
          control={control}
          name={`${fieldArrayName}.${index}.name`}
          defaultValue=""
          rules={{
            required: 'Name is required',
            pattern: {
              value: /^vm-(\w+)(\d{1,3})-(\d{1,3})$/,
              message: 'Need to be "vm-a{tenant}-999"',
            },
          }}
          render={({ field: { value, onChange }, fieldState: { error } }) => (
            <TextField
              label="Name. ex: vm-a{tenant}-100"
              value={value}
              onChange={(e) => {
                const formattedValue = formatInputValue(tenant, e.target.value);
                onChange(formattedValue);
              }}
              error={Boolean(error)}
              helperText={Boolean(error) && error.message}
            />
          )}
        />
      </Box>
    </>
  );
};

已尝试方案

曾使用react-input-mask,设置掩码为mask="vm-a{tenant}-999",但当tenant值为数字(比如999)时,会被组件的9规则(代表整数输入)替换为空,无法满足需求。

解决方案

重构formatInputValue函数,拆分输入内容的各个段,分别处理静态前缀、用户自定义字符串、tenant变量和末尾整数,实现动态适配的掩码逻辑:

import React, { useEffect } from 'react';
import { Box, TextField } from '@mui/material';
import { Controller } from 'react-hook-form';

export const Name = ({ fieldArrayName, index, setValue, watch, control }) => {
  const tenant = watch('tenant');

  useEffect(() => {
    if (tenant) setValue(`${fieldArrayName}.${index}.name`, '');
  }, [tenant, setValue, fieldArrayName, index]);

  const formatInputValue = (tenant, input) => {
    // 根据tenant是否存在,定义匹配掩码结构的正则
    const maskRegex = tenant 
      ? /^vm-(\w*)(.*?)-?(\d{0,3})$/ 
      : /^vm-(\w*)(\d{0,3})$/;

    // 提取输入中的各部分内容
    const match = input.match(maskRegex) || [];
    const customStr = match[1] || '';
    const remaining = match[2] || '';
    const digits = match[3] || '';

    // 处理自定义字符串:仅保留字母、数字、下划线
    const processedCustomStr = customStr.replace(/[^\w]/g, '');
    // 处理末尾数字:仅保留数字,最多三位
    const processedDigits = digits.replace(/\D/g, '').slice(0, 3);

    // 拼接最终的格式化值
    if (tenant) {
      return `vm-${processedCustomStr}${tenant}-${processedDigits}`;
    } else {
      return `vm-${processedCustomStr}${processedDigits}`;
    }
  };

  return (
    <Box>
      <Controller
        control={control}
        name={`${fieldArrayName}.${index}.name`}
        defaultValue=""
        rules={{
          required: 'Name is required',
          pattern: {
            value: tenant ? new RegExp(`^vm-\\w+${tenant}-\\d{1,3}$`) : /^vm-\w+\d{1,3}$/,
            message: tenant ? '格式需为 "vm-自定义字符串{tenant}-三位整数"' : '格式需为 "vm-自定义字符串三位整数"',
          },
        }}
        render={({ field: { value, onChange }, fieldState: { error } }) => (
          <TextField
            label={`Name. ex: ${tenant ? `vm-abc${tenant}-100` : 'vm-abc100'}`}
            value={value}
            onChange={(e) => {
              const formattedValue = formatInputValue(tenant, e.target.value);
              onChange(formattedValue);
            }}
            error={Boolean(error)}
            helperText={error?.message}
          />
        )}
      />
    </Box>
  );
};

关键说明

  • 动态正则:根据tenant是否存在切换匹配规则,适配两种输入结构
  • 分段处理:将输入拆分为自定义字符串、剩余内容、末尾数字三个部分,分别做格式校验和过滤
  • 动态拼接:确保vm-、自定义字符串、tenant、末尾数字的顺序始终正确
  • 适配验证:表单校验规则随tenant状态动态调整,保证输入格式符合要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:44:54