跳到主要内容

input 限制输入

· 阅读需 3 分钟
youniaogu

input 限制输入

1. 问题

很多时候需要对 input 进行输入的限制,比如只允许输入数字、英文字母和中文,不允许输入特殊字符,又或者限制长度等

第一次接触的人可能会简单的在onChangereplace

handleInputChange = evt => {
const { name, value } = evt.target

this.setState({
[name]: value.replace(/[^\u4e00-\u9fa50-9a-zA-Z]/g, ""); //除数字、英文字母和中文外都替换为‘’
})
}

<input name="name" value={name} onChange={this.handleInputChange} />

这样写的话,如果涉及到输入法时会出现错误

因为输入法键入是一个过程,而 React 中每次键入都会触发onChange,过程中输入法的一些键入被replace去除后,就会导致错误的情况

2. 解决方法

Composition Events(组成事件)里面有onCompositionStart onCompositionUpdate onCompositionEnd三个事件分别代表 开始输入合成、输入合成更新、输入合成结束

onCompositionStartonCompositionEndonChange的执行顺序有两种情况:

  1. 正常情况下:onCompositionStart -> onCompositionEnd -> onChange
  2. chrome 或 IOS 版本 10.3 及以后:onCompositionStart -> onChange -> onCompositionEnd

3. 思路

formatter部分单独拿出来,当处在onCompositionStartonCompositionUpdate状态时不触发formatter

import React from "react";

isChrome = () => {
return !!window.chrome;
};
IOSVer = () => {
const match = window.navigator.userAgent.match(/\d[\d]*_\d[_\d]*/i);
if (match) {
return parseFloat(match[0].split("-").join("."));
}
return null;
};

function Input(props) {
this.onComposition = true;
this.isChrome = isChrome();
this.IOSver = IOSVer();

handleInputChange = (evt) => {
const { name, onChange, formatter } = this.props;

if (typeof onChange === "function") {
let value = evt.target.value;
if (this.onComposition && formatter) {
value = formatter(value);
}

onChange({ target: { value, name } });
}
};
const handleComposition = (evt) => {
if (evt.type === "compositionend") {
this.onComposition = true;

if (this.isChrome || (this.IOSVer && this.IOSVer >= 10.3)) {
this.handleInputChange(evt);
}
} else {
this.onComposition = false;
}
};

const { children, onChange, formatter, ...otherProps } = props;

return (
<input
{...otherProps}
onChange={this.handleInputChange}
onCompositionStart={this.handleComposition}
onCompositionUpdate={this.handleComposition}
onCompositionEnd={this.handleComposition}
/>
);
}

export default Input;

注意的点:因为formatter部分是在onChange里执行,所以第二种情况下onCompositionEnd后需要手动触发onChange