为Web应用实现react-input-mask

756 阅读7分钟

现代网络应用程序接受各种用户输入:鼠标点击、屏幕点击和键盘事件、手势、音频和文件。几乎所有的网络应用程序都使用键盘事件来捕获详细的用户输入数据。换句话说,用户可以使用他们设备的键盘向典型的网络应用程序输入所需数据。例如,用户可以在某个网络应用程序的注册过程中输入姓名、电话号码、邮政编码和电子邮件地址,然后将这些信息传达给后端。

每个用户都是不同的。他们在填写表格时可能有独特的做法,而且他们经常试图在输入字段中使用各种格式。例如,如果一个特定的网络应用程序显示一个原始的文本输入字段来捕捉电话号码,用户可能会面临一些可用性问题,例如在他们输入时无法预测输入字段的接受格式。

为了避免这些类型的问题,你可以使用输入掩码来为特定的用户输入字段提供用户友好的约束。在这篇文章中,我将解释你如何在你的React应用程序中使用输入掩码。

什么是输入掩码?

在用户体验(UX)设计中,输入掩码是指根据特定的输入格式创建的字符串模板,以防止转写错误。如果用户试图输入一个无效的字符,被屏蔽的输入元素会阻止无效的击键。例如,用户就不能在一个被屏蔽的电话号码字段中输入英文字母。

前端开发者可以使用输入掩码来帮助确保干净有效的用户输入被发送到他们的网络应用后台。同时,输入掩码可以激励用户输入干净、正确的输入。

React应用程序中的输入掩码

有几个库,我们可以用来在React中创建输入掩码。react-input-mask 库是最流行的一个,它为开发者提供了非常灵活的 API。作为奖励,它的行为遵循一种用户体验友好的设计模式。

首先,安装react-input-mask npm包,在你的React应用程序中创建输入掩码。

npm install react-input-mask --save

现在,让我们尝试为一个电话号码创建一个简单的屏蔽输入框,以检查该库是否有效。在你的App.js 文件或组件中添加以下代码。

import { useState } from 'react';
import InputMask from 'react-input-mask';
function PhoneInput(props) {
  return (
    <InputMask 
      mask='(+1) 999 999 9999' 
      value={props.value} 
      onChange={props.onChange}>
    </InputMask>
  );
}
function App() {
  const [phone, setPhone] = useState('');
  const handleInput = ({ target: { value } }) => setPhone(value);
  return (
    <div>
      <PhoneInput 
        value={phone} 
        onChange={handleInput}>
      </PhoneInput>
      <div style={{paddingTop: '12px'}}>Phone: {phone}</div>
    </div>
  );
}
export default App;

如果你用npm startyarn start 启动React开发服务器,你会看到一个掩码输入,输入一个标准的美国电话号码(以+1拨号代码开始),如下图所示。

A simple example for masked input in React

React中屏蔽输入的一个简单例子。

我们用库的InputMask 组件实现了一个可重复使用的组件来接受电话号码。该库的通用掩码组件对以下React道具做出响应。

  • mask: 一个带有预定义特殊字符的用户输入模板 -9 用于匹配数字,a 用于匹配字母,* 用于匹配数字或字母
  • maskChar :这个字符可以用来填补输入字符串的缺失部分;默认值是_ (下划线)。
  • formatChars :你可以通过改变这个属性来改变用于屏蔽的默认字符和正则表达式(在mask 属性中)。
  • alwaysShowMask :当用户关注被屏蔽的输入时,库通常会显示屏蔽;如果你总是想显示屏蔽,则将此属性设置为true

像其他典型的输入元素一样,我们可以使用onChange 事件来根据用户输入改变组件的状态。

基本的react-input-mask 例子

输入屏蔽的概念可以在许多不同的场景中使用,以提高Web应用程序的用户友好性。请看下面的基本屏蔽例子。

4位数的PIN码

function PINInput(props) {
  return (
    <InputMask 
      mask='9999' 
      value={props.value} 
      onChange={props.onChange}
      placeholder='Enter PIN'>
    </InputMask>
  );
}

谷歌式OTP

function GoogleOTP(props) {
  return (
    <InputMask 
      mask='G-999999' 
      maskChar={null}
      value={props.value} 
      onChange={props.onChange}>
    </InputMask>
  );
}

标准信用卡

function CreditCardInput(props) {
  return (
    <InputMask 
      mask='9999 9999 9999 9999' 
      value={props.value} 
      onChange={props.onChange}>
    </InputMask>
  );
}

高级react-input-mask 例子

上述例子使用内置的正则表达式进行掩码。例如,四位数PIN的掩码使用9 来匹配数字。

然而,我们不能用这些预定义的正则表达式来实现每个屏蔽规则。换句话说,我们需要用不同的正则表达式来定义自定义屏蔽字符。在某些情况下,我们还需要有动态掩码,即用户的输入会引导他们在字段中输入的后续字符的约束。

下面,我们来看看一些使用自定义掩码字符和条件掩码的高级例子。

一个自定义的产品代码

假设你需要在一个用React编写的杂货店管理应用程序中实现一个掩码来捕获有效的产品代码。让我们这样定义一个有效产品代码的规则。

  • 每个产品代码以P (单一产品)或K (套装)开头
  • 产品代码的其余部分由四位偶数组成

我们需要定义自定义屏蔽字符来实现上述规则。请看下面的代码。

const MaskedInput = (props) => {
  // Defining custom masking characters
  // P will match P or K
  // 0 (zero) will match even digits
  const formatChars = {
    'P': '[PK]',
    '0': '[02468]'
  };
  return (<InputMask 
    mask='P0000' 
    value={props.value} 
    onChange={props.onChange}
    formatChars={formatChars}
    placeholder='Eg: P2266'>
  </InputMask>)
};

时间输入

假设你需要通过使用hh:mm 格式要求用户输入时间。时间输入掩码较简单的实现可以使用99:99 掩码,但用户仍然可以输入一些无效的时间条目,如59:1008:65 ,等等。

输入掩码通常指的是具有特定格式的字符串输入--与严格验证无关。然而,我们可以根据用户的输入应用条件性屏蔽来增加对这些场景的改进。

例如,我们可以只接受数字0,1, 和2 作为第一个屏蔽字符的位置。之后,我们可以根据用户输入的第一个数字来改变第二个屏蔽字符的逻辑。

看看下面这段使用条件掩码的代码。

function TimeInput(props) {
  let mask = '12:34';
  let formatChars = {
    '1': '[0-2]',
    '2': '[0-9]',
    '3': '[0-5]',
    '4': '[0-9]'
  };

  let beforeMaskedValueChange = (newState, oldState, userInput) => {
    let { value } = newState;

    // Conditional mask for the 2nd digit base on the first digit
    if(value.startsWith('2'))
      formatChars['2'] = '[0-3]'; // To block 24, 25, etc.
    else
      formatChars['2'] = '[0-9]'; // To allow 05, 12, etc.
    return {value, selection: newState.selection};
  }
return (
    <InputMask 
      mask={mask}
      value={props.value} 
      onChange={props.onChange}
      formatChars={formatChars}
      beforeMaskedValueChange={beforeMaskedValueChange}>
    </InputMask>
  );
}

beforeMaskedValueChange 事件将在被屏蔽的输入字段被最新的用户输入更新之前被触发。这意味着我们可以用它来动态地改变掩码。

如何设计输入掩码

react-input-mask 库使用典型的HTML输入来渲染遮罩的输入框。因此,你可以通过添加CSS类来改变造型,如你所愿。如果你想使用其他组件来代替HTML输入,比如Material,请按下面的方法实现你的组件。

import InputMask from 'react-input-mask';
import Input from '@material-ui/core/Input';

const MaskedInput = (props) => (
  <InputMask 
    mask='9999' 
    maskChar={null} 
    value={props.value} 
    onChange={props.onChange}
    placeholder='Enter your PIN'>
    {(inputProps) => <Input {...inputProps} />}
  </InputMask>
);

上面的代码片段渲染了Material输入元素,而不是原生的HTML输入元素作为屏蔽的PIN输入域。

React input masking with Material UI components

总结

输入掩码的概念适用于捕捉具有特定标准格式的用户输入,如IP地址、信用卡号码、产品代码和身份证号码等。

react-input-mask 库的维护者正计划发布一个新的稳定版本(v3.0),目前已经有一个v3.0alpha版本,对API进行了一些增强和修改。下一个稳定版本可能包含他们当前开发分支的实现。我们在本教程中使用了当前的稳定版本(v2.0.4),因为对于任何生产系统来说,不建议使用alpha版本的依赖关系。

The postImplementing react-input-mask for web appsappeared first onLogRocket Blog.