我已经创建了一个输入,它为用户输入的字符添加千个分隔符.我已经实现了代码,以防止在代码添加或删除一千个分隔符时,光标在输入末尾重新定位.但是,当光标直接放在千分隔符之前或之后时,分别按Delete或Backspace键不会删除字符.如何修改代码以启用此功能?

此外,在Reaction中有没有一种简洁的方式来创建具有这些功能的输入?

我的代码如下:

import React, { useState, useRef } from 'react';

const NumericInput = () => {
  const [value, setValue] = useState('');
  const inputRef = useRef(null);

const onKeyDown = (e) => {
  const inputElement = inputRef.current;
  const caretStart = inputElement.selectionStart;
  const caretEnd = inputElement.selectionEnd;

  if (e.key === 'Backspace' && caretStart === caretEnd && caretStart > 0) {
    const previousChar = inputElement.value.charAt(caretStart - 1);
    if (previousChar === ',' || previousChar === ' ') {
      e.preventDefault();
      inputElement.setSelectionRange(caretStart - 1, caretEnd - 1);
      return;
    }
  }

  if (e.key === 'Delete' && caretStart === caretEnd && caretEnd < inputElement.value.length) {
    const nextChar = inputElement.value.charAt(caretStart);
    if (nextChar === ',' || nextChar === ' ') {
      e.preventDefault();
      inputElement.setSelectionRange(caretStart + 1, caretEnd + 1);
      return;
    }
  }

  if (!/^-?\d*$/g.test(value) && e.key !== '-' && e.key !== 'Backspace') {
    e.preventDefault();
  }
};

  const onChange = (e) => {
    const inputValue = e.target.value.replace(/[^0-9-]/g, '');
    setValue(inputValue);

    const inputElement = inputRef.current;
    const caretPosition = Math.max(0, inputElement.selectionStart + (formatValue(inputValue).match(/,/g) || []).length - (formatValue(value).match(/,/g) || []).length);
    inputElement.value = formatValue(inputValue);
    inputElement.setSelectionRange(caretPosition, caretPosition);
  };

  const formatValue = (value) => (value ? value.replace(/\B(?=(\d{3})+(?!\d))/g, ',') : '');

  return (
      <input
        ref={inputRef}
        placeholder='Type Number'
        type='text'
        onKeyDown={onKeyDown}
        onChange={onChange}
        value={formatValue(value)}
      />
  );
};

export default NumericInput;

任何帮助都将不胜感激.谢谢!

推荐答案

你是说像这样吗?

import React, { useState, useRef } from 'react';

const NumericInput = () => {
  const [value, setValue] = useState('');
  const inputRef = useRef(null);

  const onKeyDown = (e) => {
    const inputElement = inputRef.current;
    const caretStart = inputElement.selectionStart;
    const caretEnd = inputElement.selectionEnd;

    if (e.key === 'Backspace' && caretStart === caretEnd && caretStart > 0) {
      const previousChar = inputElement.value.charAt(caretStart - 1);
      if (previousChar === ',' || previousChar === ' ') {
        inputElement.setSelectionRange(caretStart - 1, caretEnd - 1);
        return;
      }
    }

    if (e.key === 'Delete' && caretStart === caretEnd && caretEnd < inputElement.value.length) {
      const nextChar = inputElement.value.charAt(caretStart);
      if (nextChar === ',' || nextChar === ' ') {
        inputElement.setSelectionRange(caretStart + 1, caretEnd + 1);
        return;
      }
    }
  };

  const onChange = (e) => {
    const inputValue = e.target.value.replace(/[^0-9-]/g, '');
    setValue(inputValue);

    const inputElement = inputRef.current;
    const caretPosition = Math.max(0, inputElement.selectionStart + (formatValue(inputValue).match(/,/g) || []).length - (formatValue(value).match(/,/g) || []).length);
    inputElement.value = formatValue(inputValue);
    inputElement.setSelectionRange(caretPosition, caretPosition);
  };

  const formatValue = (value) => (value ? value.replace(/\B(?=(\d{3})+(?!\d))/g, ',') : '');

  return (
    <input
      ref={inputRef}
      placeholder='Type Number'
      type='text'
      onKeyDown={onKeyDown}
      onChange={onChange}
      value={formatValue(value)}
    />
  );
};

export default NumericInput;

但这个图书馆似乎运行得很好:

https://www.npmjs.com/package/react-number-format

import { NumericFormat } from "react-number-format";

export default function MainComponent() {
  return (
    <NumericFormat
      thousandSeparator={true}
    />
  );
};

Javascript相关问答推荐

为什么它无法识别日期 Select 器上的任何 Select ?

同步功能在中间停止

输入有关HTML复选框的已判断属性的信息

脚本.js:3:20未捕获的类型错误:无法读取空的属性(读取addEventHandler)

Next.js Next/Image图像隐含性有任何类型-如何修复?

类型脚本中只有字符串或数字键而不是符号键的对象

格式值未保存在redux持久切片中

Google图表时间轴—更改hAxis文本 colored颜色

Redux查询多个数据库Api reducerPath&

为什么我的列表直到下一次提交才更新值/onChange

PrivateRoute不是路由组件错误

如何为我的astro页面中的相同组件自动创建不同的内容?

WebGL 2.0无符号整数输入变量

如何将react—flanet map添加到remixjs应用程序

如何将数组用作复合函数参数?

Use Location位置成员在HashRouter内为空

TinyMCE 6导致Data:Image对象通过提供的脚本过度上载

FileReader()不能处理Firefox和GiB文件

无法设置RazorPay订阅API项目价格

Django导入问题,无法导入我的应用程序,但我已在设置中安装了它