React 实现只能输入数字的 input

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天, 点击查看活动详情

大家好,我是前端西瓜哥。

今天我们用 React 来实现一个只能输入数字的 input。

先写一个基础的 input 受控组件。

function Form() {
  const [numVal, setNumVal] = useState('');
  return (
    <input type="text" value={numVal} onChange={e => setNumVal(e.target.value)} />

上面这种写法没有做任何限制,你可以在 input 元素上输入任何内容。

只能输入数字字符

现在我们要加入限制:只能输入数字字符

很容易想到的做法是在 setNumVal 上封装多一层方法。这个方法会将 e.target.value 中非数字字符的部分移除,然后再传入到 setNumVal

function Form() {
  const [numVal, setNumVal] = useState('');
  const handleChange = (val: string) => {
    val = val.replace(/[^\d]/g, '');
    setNumVal(val);
  return (
    <input type="text" value={numVal} onChange={e => handleChange(e.target.value)} />

这里用了 string.prototype.replace 方法,/[^\d]/ 表示找非数字字符,g 表示多次查找,如果不带上,replace 只会替换第一个匹配字符串。

找到它们并将它们替换为空字符串,也就是移除掉,最后返回一个只有数字字符的字符串。

为了可以在任何的 input 或输入框组件上使用,我们不妨将其封装为 hook。

const useNumStrState = (defaultVal = ''): [string, (val: string) => void] => {
  const [numVal, setNumVal] = useState(defaultVal);
  const handleChange = (val: string) => {
    val = val.replace(/[^\d]/g, '');
    setNumVal(val);
  return [numVal, handleChange];
// 使用
function Form() {
  const [numVal, setNumVal] = useNumStrState('');
  return (
    <input type="text" value={numVal} onChange={e => setNumVal(e.target.value)} />

这样,一个有着基础能力的只能输入数字的 input 就完成了。

增强:移除前导 0 版本

下面再实现一个去掉前导 0 的版本,让用户只能输入合法的整数。

const useNumStrState = (defaultVal = ''): [string, (val: string) => void] => {
  const removeLeadingZeros = (s: string) => {
    const oldLen = s.length;
    s = s.replace(/^0+/, ''); // 移除前导零
    // 全为 0 的情况,留一个 0
    if (s.length === 0 && oldLen > 0) {
      s = '0';
    return s;
  defaultVal = removeLeadingZeros(defaultVal);
  const [numVal, setNumVal] = useState(defaultVal);
  const handleChange = (val: string) => {
    val = val.replace(/[^\d]/g, '');
    val = removeLeadingZeros(val);
    setNumVal(val);
  return [numVal, handleChange];

同样也是用 replace 方法,/^0+/ 的意思是匹配从字符串首位开始的连续尽可能多的 0,然后将它们替换为为空字符串。

这里有一种特殊的情况,就是全是 0 的字符串,比如 0000,这时候需要保留一个 0。

让 input 只能输入数字并不复杂,只需要在 onChange 的时候将 e.target.value 进行处理,得到只含数字的字符串,再用它来修改状态就好了。

另外也不得不说 React Hook 是真的牛逼,让我们可以做到比组件更细粒度的复用逻辑封装。

文章首发公众号:前端西瓜哥

分类:
前端
标签: