跳到内容
+

数字输入框

数字输入组件为用户提供一个用于整数值的字段,以及用于增加或减少值的按钮。

简介

数字输入是一种 UI 元素,它接受用户输入的数值。MUI Base 的数字输入组件是原生 HTML <input type="number"> 的可自定义替代品,它解决了其原生对应物常见的可用性问题,例如

  • 步进按钮在不同浏览器中的外观和行为不一致
  • 允许某些非数字字符 ('e', '+', '-', '.') 并静默丢弃其他字符
  • 与辅助技术不兼容且可访问性功能有限

组件

import { Unstable_NumberInput as NumberInput } from '@mui/base/Unstable_NumberInput';

以下演示展示了如何创建一个数字输入组件,应用一些样式,并使用 onChange prop 将最新值写入状态变量

Enter 键开始编辑

结构

MUI Base 数字输入组件由四个 slot 组成

  • root:一个包含其他内部 slot 的外部 <div>
  • input:一个 <input> 元素
  • incrementButton:一个用于增加值的 <button>
  • decrementButton:一个用于减少值的 <button>
<div class="base-NumberInput-root">
  <button class="base-NumberInput-decrementButton" />
  <button class="base-NumberInput-incrementButton" />
  <input class="base-NumberInput-input" />
</div>

自定义结构

使用 slots prop 来覆盖 root slot 或任何内部 slot

<NumberInput
  slots={{
    root: 'aside',
    incrementButton: CustomButton,
    decrementButton: CustomButton,
  }}
/>

使用 slotProps prop 将自定义 props 传递给内部 slot。以下代码片段

  • 将名为 my-num-input 的 CSS class 应用于 input slot
  • direction prop 传递给 increment 和 decrement button slot 中的 CustomButton 组件
<NumberInput
  slotProps={{
    input: { className: 'my-num-input' },
    incrementButton: { direction: 'UP' },
    decrementButton: { direction: 'DOWN' },
  }}
/>

Hook

import { unstable_useNumberInput as useNumberInput } from '@mui/base/unstable_useNumberInput';

useNumberInput hook 允许您将数字输入的功能应用于完全自定义的组件。它返回要放置在自定义组件上的 props,以及表示组件内部状态的字段。

Hook 不支持 slot props,但它们支持 customization props

这是一个使用 useNumberInput hook 和所有必需 props 构建的自定义组件的示例

这是一个使用 hook 的“紧凑型”数字输入组件的示例,该组件仅包含步进按钮。在此演示中,onChange 用于将组件的最新值写入状态变量。

Current value:  

自定义

最小值和最大值

使用 minmax props 定义可接受值的范围。如果您只定义其中一个,则范围的另一端将是开放式的。

// accepts any value:
<NumberInput />

// only accepts values between -10 and 10:
<NumberInput min={-10} max={10} />

// only accepts values greater than 0:
<NumberInput min={0} />

下面的演示展示了一个可接受范围为 1 到 99 的数字输入

增量步长

使用 step prop 定义在增加或减少值时值变化的粒度。例如,如果 min={0}step={2},则组件的有效值将为 0、2、4 等,因为值只能以 2 的增量更改。

// valid values: 0, 2, 4, 6, 8...
<NumberInput min={0} step={2} />

当输入字段处于焦点时,您可以输入超出有效范围的值。一旦输入字段失去焦点,该值将根据 minmaxstep 进行 clamp。

Shift 乘数

在与步进按钮交互时按住 Shift 键会将乘数(默认为 10 倍)应用于每个步长的值变化。

您可以使用 shiftMultiplier prop 自定义此行为。在以下代码片段中,如果在单击 increment 按钮时按住 Shift 键,则值将从 0 变为 5 变为 10,依此类推。

<NumberInput min={0} step={1} shiftMultiplier={5} />

事件

数字输入组件和 hook 提供了两个 props——onChangeonInputChange——它们接受组件值更改时的事件处理程序。

onChange

onChange 接受一个自定义事件处理程序,该处理程序使用两个参数调用:底层事件和最新的“clamped”值。

onChange: (
  event: React.FocusEvent<HTMLInputElement> | React.PointerEvent | React.KeyboardEvent,
  value: number | undefined,
) => void;

<input> 元素失去焦点且值已更改时,或在单击步进按钮时调用它。这是在值已根据 minmaxstep props 进行 clamp 之后。

// ✅ Works
<NumberInput
  onChange={(event, newValue) => console.log(`${event.type} event: the new value is ${newValue}`)}
/>

// ❌ Doesn't work
<NumberInput
  slotProps={{
    input: {
      // expects a native input change event handler, newValue is always undefined
      onChange: (event, newValue) => { ... },
    },
  }}
/>

onInputChange

onInputChange 接受传递给 <input> 元素的本机输入更改处理程序

onInputChange: React.ChangeEventHandler<HTMLInputElement>;

每当文本框的值更改时都会调用它——例如,在键入到其中的每个击键上,在应用 clamp 之前。

换句话说,event.target.value 可能包含超出范围的值或非数字字符。

// ✅ Works
<NumberInput
  onInputChange={(event) => console.log(`the input value is: ${event.target.value}`)}
/>

// ✅ Works
<NumberInput
  slotProps={{
    input: {
      // this exactly the same as onInputChange above
      onChange: (event) => console.log(`the input value is: ${event.target.value}`),
    },
  }}
/>

// ❌ Doesn't work
<NumberInput
  slotProps={{
    input: {
      // This will throw "unknown event handler"
      onInputChange: () => {},
    },
  }}
/>

装饰

您可以使用 startAdornmentendAdornment props 分别为数字输入添加前缀或后缀。装饰对于显示度量单位(如重量或货币)以及值非常有用。

kg