UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

469 lines (398 loc) 20.3 kB
--- localeCode: zh-CN order: 42 category: 输入类 title: InputNumber 数字输入框 icon: doc-inputnumber brief: 通过鼠标或键盘,输入范围内的数值,与 Input 不同的是它带有针对数字场景的步进器操作区,配合 Parser 使用可以展示更复杂的内容格式 --- ## 代码演示 ### 如何引入 ```jsx import import { InputNumber } from '@douyinfe/semi-ui'; ``` ### 基本输入框 ```jsx live=true 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> ); ``` ```jsx live=true 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> ); ``` ### 隐藏步进器 通过innerButtons,你可以将右侧的步进器隐藏进内部,仅hover时才会显示 ```jsx live=true import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <InputNumber innerButtons style={{ width: 190 }} /> ); ``` hideButtons设为true,彻底隐藏步进器 ```jsx live=true import React from 'react'; import { InputNumber } from '@douyinfe/semi-ui'; () => ( <InputNumber hideButtons style={{ width: 190 }} /> ); ``` ### 尺寸 ```jsx live=true 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 一对方法,一般需要同时设置,否则无法正确解析值 <Notice type="info" title="2.95.0 行为调整"> - **2.94.0 及之前**:当 InputNumber 处于**受控模式**(传入 `value`)且 `value` 为 **number** 时,首次渲染阶段输入框的展示值可能不会先经过 `formatter` 处理,组件会在 mount 后(或后续更新)再应用 `formatter/parser`,从而出现首帧展示与后续不一致的现象。 - **2.95.0 及之后**:受控模式下当 `value` 为 **number** 时,首次渲染也会应用 `formatter`(并与 `parser` 配合得到内部数值),保证首帧展示与后续一致。例如百分比场景:`value=1` 且 `formatter/parser` 使展示乘以 100 时,首帧将直接展示 `100`。 </Notice> ```jsx live=true 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> ); }; ``` ### 纯数字输入框 搭配 formatter 和 onNumberChange(**>=v1.9.0**) 可以实现纯数字输入框。 ```jsx live=true 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} /> ); } ``` ### 货币展示 2.77.0 版本开始支持货币展示,国际化模式下通过 currency={true} 开启,组件会自动根据 localeCode 展示对应货币种类。(注意切换语言类型后需要更新组件 key 值) ```jsx live=true 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 指定展示的货币种类 ```jsx live=true 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> ); }; ``` 支持 symbol、code、name 三种展示方式,通过 currencyDisplay 属性控制,默认以货币符号展示。showCurrencySymbol 设置为 false 隐藏货币符号/代码/名称的展示 ```jsx live=true 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> ); }; ``` 隐藏货币符号、代码或名称的展示,通过前后缀展示货币符号 ```jsx live=true 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> ); }; ``` ### 科学计数法显示 当数字较长时,可以通过 `scientificNotation` 属性启用科学计数法显示。失去焦点时显示科学计数法,获得焦点时显示完整数字。 ```jsx live=true 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> ); }; ``` <Notice type="info"> 科学计数法仅影响显示格式,`onChange` 和 `onNumberChange` 回调中的值仍为完整数字。该功能不支持货币模式(`currency`)。 </Notice> ## API 参考 | 属性 | 说明 | 类型 | 默认值 | 版本 | | ------------ | -------------------------------------------------------------- | --------------------------------- | --------- | --------- | | autofocus | 自动获取焦点 | boolean | false | | | className | 类名 | string | - | | clearIcon | 可用于自定义清除按钮, showClear为true时有效 | ReactNode | | 2.25.0| | currency | 货币种类,国际化模式下通过 currency={true} 开启,组件会自动根据 locale 展示对应货币种类, 也可以手动传入 localeCode 和 currency 指定展示的货币种类, currency 的可选值有 `CNY`,`EUR`,`USD`等| boolean\|string | false | **2.77.0** | | currencyDisplay | 货币展示方式,可选值:symbol、code、name | string | symbol | **2.77.0** | | defaultValue | 默认值 | number | | | | disabled | 禁用 | boolean | false | | | formatter | 指定输入框展示值的格式 | (value: number\|string) => string | - | | | hideButtons | 为 `true` 时隐藏 "上/下" 按钮 | boolean | false | - | | innerButtons | 为 `true` 时 "上/下" 按钮显示在输入框内部 | boolean | false | - | | keepFocus | 点击按钮时保持输入框聚焦 | boolean | false | - | | localeCode | 货币模式下用于指定国家地区代码,可选值有 `zh-CN`, `en-US`, `en-GB`, `ja-JP`, `ko-KR`, `ar`, `vi-VN`, `ru-RU`, `id-ID`, `ms-MY`, `th-TH`, `tr-TR`, `pt-BR`, `zh-TW`, `es`, `de`, `it`, `fr`, `ro`, `sv-SE`, `pl-PL`, `nl-NL`等 | string | - | **2.77.0** | | max | 限定最大值 | number | Infinity | | | min | 限定最小值 | number | -Infinity | | | parser | 指定从 `formatter` 里转换回数字串的方式,和 `formatter` 搭配使用 | (str: string) => string | - | | | precision | 数值精度 | number | - | | | prefix | 前缀内容 | string\|ReactNode | | | | pressInterval| 长按按钮时,多久触发一次点击事件,单位毫秒 | number | 250 | | | pressTimeout | 长按按钮时,延迟多久后触发点击事件,单位毫秒 | number | 250 | | | preventScroll | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法 | boolean | | | | scientificNotation | 启用科学计数法显示,失去焦点时显示科学计数法,获得焦点时显示完整数字。可传入对象配置阈值 `threshold`,默认为 15 位有效数字。不支持货币模式 | boolean\|{ threshold?: number } | false | **2.97.0** | | shiftStep | 按住 shift 键每次改变步数,可以为小数,v2.13 默认值由 1 调整为 10 | number | 10 | - | | showClear | 是否显示清除按钮 | boolean | false | - | | showCurrencySymbol | 是否显示货币符号/代码/名称,仅货币模式下生效 | boolean | true | **2.77.0** | | size | 输入框大小,可选值:"default"\|"small"\|"large" | string | 'default' | | | step | 每次改变步数,可以为小数 | number | 1 | | | style | 样式 | CSSProperties | - | | suffix | 自定义后缀 | ReactNode | | | | value | 当前值 | number | | | | onBlur | 失去焦点时的回调 | (e: domEvent) => void | () => {} | - | | onChange | 变化回调 | (value: number\|string) => void | - | | | onFocus | 获得焦点时的回调 | (e: domEvent) => void | () => {} | - | | onNumberChange | 数字变化回调 | (value: number) => void | - | - | ## Methods 绑定在组件实例上的方法,可以通过 ref 调用实现某些特殊交互 | 名称 | 描述 | | ------- | -------- | | blur() | 移出焦点 | | focus() | 获取焦点 | ## Accessibility 参考标准:https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/ ### ARIA - 数字输入框具有 spinbutton role - spinbutton 使用 aria-valuenow 表示当前值,aria-valuemax 表示可以接受的最大值,aria-valuemin 表示可以接受的最小值 - 当 InputNumber 在 Form 中使用时,输入框的 aria-labeledby 指向 Field label ### 键盘和焦点 - InputNumber 可被获取焦点,键盘用户可以使用 Tab 及 Shift + Tab 切换焦点(增加/减少按钮不可以被键盘聚焦) - 键盘用户可以按上键 ⬆️ 或下键 ⬇️ ,输入值将增加或减少 step(默认值为 1) - 按住 Shift + 上键 ⬆️ 或下键 ⬇️ ,输入值将增加或减少 shiftStep(默认值为 10) ## 设计变量 <DesignToken/>