news 2026/9/24 17:22:05

Semi Design InputNumber 数字输入框完全指南:步进器交互、格式化解析、货币展示与科学计数法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Semi Design InputNumber 数字输入框完全指南:步进器交互、格式化解析、货币展示与科学计数法
  • 前端
  • UI组件
  • 设计系统

【免费下载链接】semi-design

🚀A modern, comprehensive, flexible design system and React UI library, AI-friendly built-in.🎨Provide 3000+ Design Tokens, easy to build your design system. Make Semi Design to Any Design.🧑🏻‍💻 Design to Code in one click

项目地址:https://gitcode.com/gh_mirrors/se/semi-design
点击查看免费下载

本文围绕 Semi Design 组件库的InputNumber数字输入框展开,系统讲解其引入方式、步进器交互(step/shiftStep/innerButtons/长按连发)、formatter/parser自定义格式化、currency国际化货币展示与scientificNotation科学计数法显示等核心能力,并结合 packages/semi-ui/inputNumber/index.tsx 与 packages/semi-foundation/inputNumber/foundation.ts 的源码实现,说明各配置项背后的真实工作机制。读完本文,你将能够在 Semi 项目中熟练实现带范围约束、格式化展示、货币/多语言与超长数字场景的数字输入方案。

组件定位与引入

InputNumber是 Semi Design 提供的数字输入组件,与普通Input的区别在于:它面向“数值”场景内置了步进器(上/下按钮)操作区,同时通过parserformatter的配合,可以展示比纯数字更复杂的内容格式(如千分位货币、自定义分隔串等)。完整示例与 API 说明见文档 content/input/inputnumber/index.md。

从组件库中直接引入即可使用:

import { InputNumber } from '@douyinfe/semi-ui';

组件在semi-ui包中的实现入口为 packages/semi-ui/inputNumber/index.tsx,它通过forwardStatics包裹React.forwardRef,并默认套上一层LocaleConsumer,因此InputNumber会自动感知全局LocaleProvider的语言环境(locale),这也是货币模式默认值的重要前提。

基础用法:步长、范围、默认值与精度

最简用法与常用属性组合

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <div style={{ width: 280 }}> <label>简单数字输入框</label> <InputNumber /> <br/><br/> <label>设置了步长 step=2 </label> <InputNumber step={2} /> <br/><br/> <label>设置 shiftStep=100,按住 shift 同时点击按钮,可以一次增加/减少100 </label> <InputNumber shiftStep={100} /> <br/><br/> <label>设置了上下界 min=1,max=10</label> <InputNumber min={1} max={10} defaultValue={1} /> <br/><br/> </div> );
import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <div style={{ width: 280 }}> <label>设置了默认值 defaultValue=1 </label> <InputNumber defaultValue={1} /> <br/><br/> <label>禁用 disabled=true</label> <InputNumber defaultValue={2} disabled /> <br/><br/> <label>设置了小数位数 precision=2 </label> <InputNumber precision={2} defaultValue={1.234} /> <br/><br/> <label>设置了 innerButtons=true </label> <InputNumber innerButtons={true} suffix={'小时'} defaultValue={1} style={{ width: 190 }} /> <br/> </div> );

关键属性的默认值与边界

依据 packages/semi-foundation/inputNumber/constants.ts 与 index.tsx 中的defaultProps,各核心参数的默认值如下:

属性默认值说明
step1每次点击/按键改变的量,可为小数
shiftStep10(v2.13 起由1调整为10按住 Shift 时每次改变的量,可为小数
min/max-Infinity/Infinity数值上下界,不传则不受限
precision小数精度,传入后会在解析/失焦时对数值做toFixed(precision)处理
pressTimeout250(毫秒)长按按钮时,延迟多久后开始连发
pressInterval250(毫秒)长按按钮时,连发阶段的触发间隔

注意:DEFAULT_PRESS_INTERVAL在 constants.ts 中定义为0,而组件defaultPropspressInterval取的是numbers.DEFAULT_PRESS_TIMEOUT(即 250);foundation 中_registerInterval读取 prop 失败时才回退到DEFAULT_PRESS_INTERVAL。实际效果以 props 传入值为准,不传即 250ms。

边界约束的底层实现

min/max的约束并不是仅在点击按钮时生效:在 foundation.ts 中,fetchMinOrMax会在解析(doParse)与格式化(doFormat)阶段对数值做钳制;add/minus计算步进结果时,也会先判断“当前值距离边界是否仍大于等于步长”,避免越界(foundation.ts)。isValidNumber(foundation.ts)则要求数值同时满足「类型为 number 且非 NaN」「在[min, max]区间内」「小数位数不超过precision」三个条件才算合法。

步进器控制:innerButtons、hideButtons 与长按连发

两种隐藏步进器的方式

innerButtons将步进器收纳进输入框内部,仅在 hover 时显示,适合追求紧凑界面的场景:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <InputNumber innerButtons style={{ width: 190 }} /> );

hideButtons设为true则彻底隐藏步进器:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <InputNumber hideButtons style={{ width: 190 }} /> );

从源码看,这两者共用同一套步进按钮渲染逻辑 index.tsx:innerButtons模式下按钮作为suffix渲染,且仅当hovering && !focusing时展示(renderSuffix中判断innerButtons && (hovering || focusing));hideButtonsinnerButtons为真时,外层不再渲染独立按钮区域。

长按连发与 keepFocus

步进按钮支持按住连续触发handleUpClick/handleDownClick在触发一次后,会通过_registerTimer(延迟pressTimeout)再注册_registerInterval(间隔pressInterval)实现持续步进;松开鼠标(handleMouseUp)或移出按钮时注销定时器(foundation.ts)。这两个时间参数即上表 API 中的pressTimeout/pressInterval

keepFocus用于点击步进按钮时保持输入框焦点不丢失(适合需要连续调整数值、又不希望触发失焦逻辑的场景)。测试用例(packages/semi-ui/inputNumber/test/inputNumber.test.js)中也有keepFocus与按钮点击组合的受控模式验证。

尺寸

size支持"default""large""small"三种取值,控制输入框整体高度,内部通过semi-input-{size}类名生效:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <div style={{ width: 180 }}> <label>默认尺寸 size=default</label> <InputNumber /> <br/><br/> <label>大尺寸 size=large</label> <InputNumber size="large" /> <br/><br/> <label>小尺寸 size=small</label> <InputNumber size="small" /> <br/> </div> );

formatter 与 parser:自定义显示格式与解析

成对使用是前提

formatter决定“输入框里展示成什么样子”,parser决定“从展示串还原出数字串”,两者一般需要同时设置,否则无法正确解析值。示例中通过onChange打印值的实际类型与内容,方便观察解析结果:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => { const log = (v) => { console.log(`Changed to: [${typeof v}] ${v}`); }; return ( <div style={{ width: 180 }}> <label>人民币</label> <InputNumber onChange={this.log} defaultValue={1000} min={0} formatter={value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/\¥\s?|(,*)/g, '')} /> <br/><br/> <label>自定义串</label> <InputNumber onChange={this.log} defaultValue={1111} formatter={value => String(value).split('').join('-')} parser={value => value.replace(/\-/g, '')} /> <br/> </div> ); };

第一个示例演示千分位货币串1,000),第二个演示自定义分隔串1-1-1-1)。注意两个示例都同时提供了配套的parser将展示串还原为纯数字,否则格式化后的字符串无法被正确解析回数值。

2.95.0 行为调整:受控模式首帧即应用 formatter

官方文档特别提示了 2.95.0 的行为变更(见 content/input/inputnumber/index.md):

  • 2.94.0 及之前:当InputNumber处于受控模式(传入value)且valuenumber时,首次渲染阶段输入框的展示值可能不会先经过formatter处理,组件会在 mount 后(或后续更新)再应用formatter/parser,从而出现首帧展示与后续不一致的现象。
  • 2.95.0 及之后:受控模式下当valuenumber时,首次渲染也会应用formatter(并与parser配合得到内部数值),保证首帧展示与后续一致。例如百分比场景:value=1formatter/parser使展示乘以 100 时,首帧将直接展示100

这一修复与 index.tsx 中constructor里通过_getInitState初始化 state 的实现直接相关——初始化时若传入的是 number,会先调用foundation.doFormat格式化、再doParse得到内部数值,从而保证首帧即经过 formatter 处理。

纯数字输入框(v1.9.0+)

搭配formatteronNumberChange>= v1.9.0)可以实现“只允许纯数字”的输入框:formatter将非数字字符过滤掉,onNumberChange拿到过滤后的 number 值:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; function Demo () { return ( <InputNumber formatter={value => `${value}`.replace(/\D/g, '')} onNumberChange={number => console.log(number)} min={0} max={Number.MAX_SAFE_INTEGER} /> ); }

这里的min/max设置了0Number.MAX_SAFE_INTEGER的合法区间,防止过滤后的空串或非法值被当作合法数字处理。

formatter/parser 在源码中的调用链

在 foundation.ts 中:

  • doFormat(value, needAdjustPrec, needAdjustCurrency)(L638-L667)负责“数字 → 展示串”:先做精度调整/货币格式化,再在最后套用formatter
  • doParse(value, needCheckPrec, needAdjustPrec, needAdjustMaxMin)(L709-L771)负责“展示串 → 数字”:先调用parser还原,再做精度、范围钳制与科学计数法解析。
  • 用户输入的每一帧都会经过handleInputChange(L191-L258):非法字符会被 parser 过滤后重新格式化展示,保证“所有输入都经过 parser 和 format 处理”;失焦时handleInputBlur会再次校验并格式化为规范展示。

货币展示(2.77.0+)

国际化模式:currency={true}

2.77.0起支持货币展示。国际化模式下通过currency={true}开启,组件会根据LocaleProviderlocale自动展示对应货币种类。以下示例内置了 20+ 语言切换,切换语言类型后需要更新组件key(示例中使用key={localeCode})以强制重建组件、刷新货币符号:

import React, { useCallback, useMemo, useState } from 'react'; import zh_CN from '@douyinfe/semi-ui/lib/es/locale/source/zh_CN'; import en_GB from '@douyinfe/semi-ui/lib/es/locale/source/en_GB'; import en_US from '@douyinfe/semi-ui/lib/es/locale/source/en_US'; import ko_KR from '@douyinfe/semi-ui/lib/es/locale/source/ko_KR'; import ja_JP from '@douyinfe/semi-ui/lib/es/locale/source/ja_JP'; import ar from '@douyinfe/semi-ui/lib/es/locale/source/ar'; import vi_VN from '@douyinfe/semi-ui/lib/es/locale/source/vi_VN'; import ru_RU from '@douyinfe/semi-ui/lib/es/locale/source/ru_RU'; import id_ID from '@douyinfe/semi-ui/lib/es/locale/source/id_ID'; import ms_MY from '@douyinfe/semi-ui/lib/es/locale/source/ms_MY'; import th_TH from '@douyinfe/semi-ui/lib/es/locale/source/th_TH'; import tr_TR from '@douyinfe/semi-ui/lib/es/locale/source/tr_TR'; import pt_BR from '@douyinfe/semi-ui/lib/es/locale/source/pt_BR'; import zh_TW from '@douyinfe/semi-ui/lib/es/locale/source/zh_TW'; import sv_SE from '@douyinfe/semi-ui/lib/es/locale/source/sv_SE'; import pl_PL from '@douyinfe/semi-ui/lib/es/locale/source/pl_PL'; import nl_NL from '@douyinfe/semi-ui/lib/es/locale/source/nl_NL'; import es from '@douyinfe/semi-ui/lib/es/locale/source/es'; import it from '@douyinfe/semi-ui/lib/es/locale/source/it'; import de from '@douyinfe/semi-ui/lib/es/locale/source/de'; import fr from '@douyinfe/semi-ui/lib/es/locale/source/fr'; import ro from '@douyinfe/semi-ui/lib/es/locale/source/ro'; import { LocaleProvider, InputNumber, Select } from '@douyinfe/semi-ui'; function I18nDemo() { const [locale, setLocale] = useState(zh_CN); const [localeCode, setLocaleCode] = useState('zh_CN'); const language = useMemo(() => ({ 'zh_CN': zh_CN, 'en_GB': en_GB, 'en_US': en_US, 'ko_KR': ko_KR, 'ja_JP': ja_JP, 'ar': ar, 'vi_VN': vi_VN, 'ru_RU': ru_RU, 'id_ID': id_ID, 'ms_MY': ms_MY, 'th_TH': th_TH, 'tr_TR': tr_TR, 'pt_BR': pt_BR, 'zh_TW': zh_TW, 'es': es, 'sv_SE': sv_SE, 'pl_PL': pl_PL, 'nl_NL': nl_NL, de, it, fr, ro }), []); const onLanguageChange = (code) => { setLocale(language[code]); setLocaleCode(code); }; return ( <> <div style={{ paddingBottom: 20 }}> <Select onChange={onLanguageChange} insetLabel='切换语言' style={{ width: 250 }} defaultValue='zh_CN'> <Select.Option value='zh_CN'>简体中文</Select.Option> <Select.Option value='en_US'>英语(美)</Select.Option> <Select.Option value='en_GB'>英语(英)</Select.Option> <Select.Option value='ja_JP'>日语</Select.Option> <Select.Option value='ko_KR'>韩语</Select.Option> <Select.Option value='ar'>阿拉伯语</Select.Option> <Select.Option value='vi_VN'>越南语</Select.Option> <Select.Option value='ru_RU'>俄罗斯语</Select.Option> <Select.Option value='id_ID'>印尼语</Select.Option> <Select.Option value='ms_MY'>马来语</Select.Option> <Select.Option value='th_TH'>泰语</Select.Option> <Select.Option value='tr_TR'>土耳其语</Select.Option> <Select.Option value='pt_BR'>葡萄牙语(巴西)</Select.Option> <Select.Option value='zh_TW'>繁体中文</Select.Option> <Select.Option value='es'>西班牙语</Select.Option> <Select.Option value='de'>德语</Select.Option> <Select.Option value='it'>意大利语</Select.Option> <Select.Option value='fr'>法语</Select.Option> <Select.Option value='ro'>罗马尼亚语</Select.Option> <Select.Option value='sv_SE'>瑞典语</Select.Option> <Select.Option value='pl_PL'>波兰语</Select.Option> <Select.Option value='nl_NL'>荷兰语</Select.Option> </Select> </div> <LocaleProvider locale={locale}> <InputNumber key={localeCode} currency={true} defaultValue={123456.78} /> </LocaleProvider> </> ); }

手动指定 localeCode 与 currency

也可以手动传localeCodecurrency直接指定展示的货币种类,不依赖全局 Locale:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => { const defaultValue = 123456.78; return ( <div> <div>🇨🇳 人民币</div> <InputNumber localeCode="zh-CN" currency="CNY" defaultValue={defaultValue} /> <br /> <br /> <div>🇪🇺 欧元</div> <InputNumber localeCode="de-DE" currency="EUR" defaultValue={defaultValue} /> <br /> <br /> <div>🇯🇵 日元</div> <InputNumber localeCode="ja-JP" currency="JPY" defaultValue={defaultValue} /> <br /> <br /> <div>🇻🇳 越南盾</div> <InputNumber localeCode="vi-VN" currency="VND" defaultValue={defaultValue} /> <br /> <br /> </div> ); };

currencyDisplay 三种展示方式与 showCurrencySymbol

支持symbol(货币符号,默认)、code(货币代码)、name(货币名称)三种展示方式,通过currencyDisplay属性控制:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => { const defaultValue = 123456.78; return ( <div> <div>🇨🇳 CNY ➕ code</div> <InputNumber currency="CNY" currencyDisplay="code" defaultValue={defaultValue} /> <br /> <br /> <div>🇨🇳 CNY ➕ symbol</div> <InputNumber currency="CNY" currencyDisplay="symbol" defaultValue={defaultValue} /> <br /> <br /> <div>🇨🇳 CNY ➕ name</div> <InputNumber currency="CNY" currencyDisplay="name" defaultValue={defaultValue} /> <br /> <br /> </div> ); };

showCurrencySymbol设置为false可以隐藏货币符号/代码/名称的展示,此时通常配合prefix/suffix自行展示货币标识:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => { const defaultValue = 123456.78; return ( <div> <div>🇨🇳 CNY ➕ code</div> <InputNumber style={{ width: 200 }} currency="CNY" prefix="CNY" showCurrencySymbol={false} defaultValue={defaultValue} /> <br /> <br /> <div>🇨🇳 CNY ➕ symbol</div> <InputNumber style={{ width: 200 }} currency="CNY" prefix="¥" showCurrencySymbol={false} defaultValue={defaultValue} /> <br /> <br /> <div>🇨🇳 CNY ➕ name</div> <InputNumber style={{ width: 200 }} currency="CNY" suffix="人民币" showCurrencySymbol={false} defaultValue={defaultValue} /> <br /> <br /> </div> ); };

货币模式的底层实现

货币展示依赖浏览器原生Intl.NumberFormatformatCurrency(foundation.ts)用style: 'currency'格式化数值,并支持minimumFractionDigits/maximumFractionDigits(可回退到precision);_setCurrencySymbol则通过formatToParts提取当前 locale 下的小数点符号与货币符号(foundation.ts),供parseInternationalCurrency将货币串还原为纯数字。

getCurrencyByLocaleCode(foundation.ts)内置了一张地区码 → 货币码映射表(如zh-CN → CNYja-JP → JPYde-DE → EURen-US → USD等),未命中时按语言前缀回退(en → USDzh → CNY),最后兜底USD。测试用例(packages/semi-ui/inputNumber/test/inputNumber.test.js)覆盖了 CNY/USD/EUR/JPY/VND/THB/IDR 等常见货币及showCurrencySymbol={false}currencyDisplay三种展示方式的格式化结果。

科学计数法显示(2.97.0+)

当数字较长时,可通过scientificNotation属性启用科学计数法显示:失去焦点时显示科学计数法,获得焦点时显示完整数字。默认阈值为 15 位有效数字,也可传入对象自定义阈值:

import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => { return ( <div style={{ width: 280 }}> <label>启用科学计数法(默认阈值 15 位)</label> <InputNumber scientificNotation defaultValue={123456789012345} /> <br /><br /> <label>自定义阈值(10 位)</label> <InputNumber scientificNotation={{ threshold: 10 }} defaultValue={1234567890} /> <br /><br /> <label>超大数字</label> <InputNumber scientificNotation defaultValue={9999999999999999} /> <br /><br /> <label>小数场景</label> <InputNumber scientificNotation precision={10} defaultValue={0.000000123456789} /> <br /><br /> </div> ); };

注意事项(文档原文明确声明):

科学计数法仅影响显示格式,onChangeonNumberChange回调中的值仍为完整数字。该功能不支持货币模式(currency)。

在源码层面,_getScientificNotationThreshold(foundation.ts)读取scientificNotation.threshold,默认 15;_toScientificNotation(foundation.ts)统计有效数字位数(排除小数点、正负号、指数符号与前导零),超过阈值时用num.toExponential()生成科学计数法串并去掉系数尾部多余的零;doFormat仅在“失焦展示态”(needAdjustCurrency=true且非货币模式)下应用科学计数法;handleInputFocus在聚焦时检测到科学计数法串(形如1.23e+15)会还原为完整数字再展示(foundation.ts)。doParse中也内置了对科学计数法字符串(如"1.23e+15""1.23E-10")的解析支持。

API 参考

以下为 content/input/inputnumber/index.md 中完整 API 表,并结合源码补充了默认值与版本信息:

属性说明类型默认值版本
autofocus自动获取焦点booleanfalse
className类名string-
clearIcon自定义清除按钮,showClear 为 true 时有效ReactNode-2.25.0
currency货币种类,国际化模式下通过currency={true}开启,组件自动根据 locale 展示对应货币;也可手动传入localeCodecurrency指定。可选值如CNYEURUSDboolean|stringfalse2.77.0
currencyDisplay货币展示方式:symbolcodenamestringsymbol2.77.0
defaultValue默认值number-
disabled禁用booleanfalse
formatter指定输入框展示值的格式(value: number|string) => string-
hideButtonstrue时隐藏"上/下"按钮booleanfalse
innerButtonstrue时"上/下"按钮显示在输入框内部booleanfalse
keepFocus点击按钮时保持输入框聚焦booleanfalse
localeCode货币模式下指定国家地区代码,可选值如zh-CNen-USen-GBja-JPko-KRarvi-VNru-RUid-IDms-MYth-THtr-TRpt-BRzh-TWesdeitfrrosv-SEpl-PLnl-NLstring-2.77.0
max限定最大值numberInfinity
min限定最小值number-Infinity
parser指定从formatter里转换回数字串的方式,和formatter搭配使用(str: string) => string-
precision数值精度number-
prefix前缀内容string|ReactNode-
pressInterval长按按钮时,多久触发一次点击事件(毫秒)number250
pressTimeout长按按钮时,延迟多久后触发点击事件(毫秒)number250
preventScroll指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法boolean-
scientificNotation启用科学计数法显示:失焦显示科学计数法、聚焦显示完整数字。可传对象配置阈值threshold,默认 15 位有效数字。不支持货币模式boolean|{ threshold?: number }false2.97.0
shiftStep按住 shift 键每次改变步数,可为小数,v2.13 默认值由 1 调整为 10number10
showClear是否显示清除按钮booleanfalse
showCurrencySymbol是否显示货币符号/代码/名称,仅货币模式下生效booleantrue2.77.0
size输入框大小:"default"|"small"|"large"string'default'
step每次改变步数,可以为小数number1
style样式CSSProperties-
suffix自定义后缀ReactNode-
value当前值(受控)number-
onBlur失去焦点时的回调(e: domEvent) => void() => {}
onChange变化回调(value: number|string) => void-
onFocus获得焦点时的回调(e: domEvent) => void() => {}
onNumberChange数字变化回调(纯数字场景,>= v1.9.0)(value: number) => void-

补充说明:组件内部还暴露了onUpClick(value, e)/onDownClick(value, e)两个步进按钮点击回调(见 index.tsx 的 Props 类型),可在需要感知步进方向时使用。onChangeonNumberChange的差异在于:onChange可能回传格式化后的字符串或数字,onNumberChange仅在有意义的数值变化时回传 number(notifyNumberChange会过滤掉非显著变化,见 foundation.ts)。

Methods

以下方法绑定在组件实例上,可通过ref调用实现某些特殊交互:

名称描述
blur()移出焦点
focus()获取焦点

使用示例(ref 同时支持对象与函数两种形式,测试用例中有对应验证):

import React, { useRef } from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; function Demo() { const ref = useRef(null); return ( <> <InputNumber ref={ref} /> <button onClick={() => ref.current.focus()}>聚焦</button> <button onClick={() => ref.current.blur()}>失焦</button> </> ); }

Accessibility:无障碍与键盘交互

参考标准:W3C WAI-ARIA APG 的 spinbutton 模式(https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/)。

ARIA

  • 数字输入框具有spinbuttonrole;
  • spinbutton 使用aria-valuenow表示当前值,aria-valuemax表示可接受的最大值,aria-valuemin表示可接受的最小值;
  • InputNumberForm中使用时,输入框的aria-labelledby指向 Field label。

以上语义在源码渲染层有直接体现:组件向内部Input传入role="spinbutton",并仅在number存在时设置aria-valuenow、在max !== Infinity时设置aria-valuemax、在min !== -Infinity时设置aria-valuemin(index.tsx)。

键盘和焦点

  • InputNumber可被获取焦点,键盘用户可以使用 Tab 及 Shift + Tab 切换焦点(增加/减少按钮不可以被键盘聚焦);
  • 键盘用户可以按上键 ⬆️ 或下键 ⬇️,输入值将增加或减少step(默认值为 1);
  • 按住 Shift + 上键 ⬆️ 或下键 ⬇️,输入值将增加或减少shiftStep(默认值为 10)。

键盘上下键的响应在handleInputKeyDown中实现(foundation.ts):检测到 UP/DOWN 键码后,分别调用add/minus计算新值,再通过_doInput更新并触发onChange,同时event.preventDefault()阻止输入框内光标跳动。Shift 的判定在add/minus中通过event.shiftKey完成(foundation.ts),按 Shift 时使用shiftStep,否则使用step

与 Form 表单的配合

InputNumber可在Form中作为字段使用,测试代码(packages/semi-ui/inputNumber/test/inputNumber.test.js)中引入了FormwithFielduseFormApi进行联动验证。在Form.Field中直接放置InputNumber即可获得校验、label 关联(aria-labelledby)与取值能力,适合数量、金额、百分比等数值型表单字段。

总结

InputNumber是 Semi Design 中面向数值输入场景的高频组件,核心能力可归纳为四点:

  1. 步进交互step/shiftStep控制增减粒度,innerButtons/hideButtons控制步进器形态,pressTimeout/pressInterval支持长按连发;
  2. 格式化解析formatterparser成对使用实现任意展示格式,2.95.0 起受控模式首帧即应用 formatter;
  3. 国际化货币:2.77.0 起基于Intl.NumberFormat与 locale 映射实现多语言货币展示,currencyDisplayshowCurrencySymbol精细控制展示形式;
  4. 长数字场景:2.97.0 起的scientificNotation让超长数字在失焦时以科学计数法呈现、聚焦时还原完整数值。

配合onNumberChangemin/max/precision约束与完整的 ARIA/键盘无障碍支持,InputNumber可以覆盖从基础数值输入到复杂货币格式化的绝大多数业务场景。所有能力的实现细节均可追溯至 packages/semi-ui/inputNumber/index.tsx 与 packages/semi-foundation/inputNumber/foundation.ts,读者可结合源码进一步深入。

  • 前端
  • UI组件
  • 设计系统

【免费下载链接】semi-design

🚀A modern, comprehensive, flexible design system and React UI library, AI-friendly built-in.🎨Provide 3000+ Design Tokens, easy to build your design system. Make Semi Design to Any Design.🧑🏻‍💻 Design to Code in one click

项目地址:https://gitcode.com/gh_mirrors/se/semi-design
点击查看免费下载

相关推荐

上一篇:基于《老乡鸡菜品溯源报告》的金汤酸菜鱼标准化复刻指南(CookLikeHOC 煮锅系列)
下一篇:OpenClaw 云端部署实战:基于 Cloudflare Containers、Durable Objects 与 Litestream R2 的容器化方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 17:19:41

【MATLAB例程】三维RRT路径规划与TOA-AOA-TDOA融合定位算法。附下载链接,代码有中文注释、包运行成功

原创代码&#xff0c;请勿翻卖 文章目录程序简介路径规划模型量测模型运行结果MATLAB源代码程序简介 本程序实现三维RRT避障路径规划与TOA、AOA、TDOA融合定位&#xff0c;并对三维轨迹及定位误差进行分析。地图范围、三维障碍物、起终点、锚节点位置、RRT规划参数及量测噪声等…

作者头像 李华