@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.
359 lines (294 loc) • 24.9 kB
Markdown
---
localeCode: zh-CN
order: 50
category: 输入类
title: TimePicker 时间选择器
icon: doc-timepicker
brief: 用户使用时间选择器可以方便地选择某一符合要求的、格式化的时间点
---
## 代码演示
### 如何引入
```jsx import
import { TimePicker } from '@douyinfe/semi-ui';
```
### 基础使用
点击 TimePicker,然后可以在浮层中选择或者输入某一时间。
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return <TimePicker />;
}
```
### 无限滚动
版本V2.22.0开始,我们将 TimePicker 内的 ScrollItem 的默认模式从 `wheel` 变更为了 `normal`, 若想应用回无限滚动的效果,可参考以下示例。
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return <TimePicker scrollItemProps={{ mode: "wheel", cycled: true }}/>;
}
```
### 受控组件
当使用 `value` 而不是 `defaultValue` 时,作为受控组件使用。`value` 和 `onChange` 需要配合使用。
```jsx live=true hideInDSM
import React, { useState } from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
() => {
const [value, setValue] = useState(null);
const onChange = (time) => {
console.log(time);
setValue(time);
};
return <TimePicker value={value} onChange={onChange} />;
};
```
### 不同的 Format 格式
TimePicker 浮层中的列会随着 `format` 变化,当略去 `format` 中的某部分时,浮层中对应的列也会消失。
NOTE: `format` 遵循 date-fns 的 `format` 格式。 https://date-fns.org/v2.0.0/docs/format
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return <TimePicker format={'HH:mm'} defaultValue={'10:24'}/>;
}
```
### 设置面板头部,底部
```jsx live=true
import React, { useState } from 'react';
import { TimePicker, Button } from '@douyinfe/semi-ui';
function Demo() {
const [open, setOpen] = useState(false);
const closePanel = () => setOpen(false);
const onOpenChange = (open) => {
setOpen(open);
console.log(open);
};
return (
<div>
<TimePicker
open={open}
onOpenChange={onOpenChange}
panelHeader={'Time Select'}
panelFooter={<Button onClick={closePanel}>close</Button>}
/>
<br/><br/>
<TimePicker
type='timeRange'
panelHeader={['start header', 'end header']}
panelFooter={[
<Button key="1" onClick={() => {console.log('start footer');}}>start footer</Button>,
<Button key="2" onClick={() => {console.log('end footer');}}>end footer</Button>
]}
/>
</div>
);
}
```
### 禁用时间选择
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return <TimePicker defaultValue={'12:08:23'} disabled />;
}
```
### 设置步长
可以使用 `hourStep`, `minuteStep`, `secondStep` 按步长展示可选的时分秒。
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return <TimePicker minuteStep={15} secondStep={10} />;
}
```
### 12 小时制
12 小时制的时间选择器,默认的 `format` 为 `h:mm:ss a`,传入的 `format` 格式必须在 [dateFns 日期格式](https://date-fns.org/v2.0.0/docs/format)范围之内。
> 例如默认的 12 小时制格式串为:`a h:mm:ss`,如果传入 `A h:mm:ss` 则会导致无法正确格式化。
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return (
<div>
<TimePicker use12Hours /><br/><br/>
<TimePicker use12Hours format="a h:mm" />
</div>
);
}
```
### 时间范围
传入 type="timeRange" 开启时间范围选择。
```jsx live=true
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return (
<div>
<TimePicker type="timeRange" defaultValue={["10:23:15", "12:38:32"]} /><br/><br/>
<TimePicker type="timeRange" use12Hours format="a h:mm" defaultValue={["上午 08:11", "下午 11:21"]} />
</div>
);
}
```
### Range 模式下分别禁用左右面板(disabledTime)
当 `type="timeRange"` 时,你可以通过 `disabledTime(value, panelType)` 对左右面板分别应用不同的禁用规则。
- `value`:单选模式为 `Date`;range 模式为 `Date[]`(可能为空/长度为 1/2)
- `panelType`:`'left' | 'right'`,分别代表开始/结束面板
下面示例实现:选择开始时间后,右侧结束时间面板会禁用早于开始时间的选项。
```jsx live=true hideInDSM
import React from 'react';
import { TimePicker } from '@douyinfe/semi-ui';
function Demo() {
return (
<TimePicker
type="timeRange"
disabledTime={(value, panelType) => {
const start = Array.isArray(value) ? value[0] : value;
if (panelType === 'right' && start instanceof Date) {
const h = start.getHours();
const m = start.getMinutes();
return {
disabledHours: () => Array.from({ length: h }, (_, i) => i),
disabledMinutes: hour => (hour === h ? Array.from({ length: m }, (_, i) => i) : []),
};
}
return {};
}}
/>
);
}
```
### 自定义触发器
默认情况下我们使用 `Input` 组件作为 `TimePicker` 组件的触发器,通过传递 `triggerRender` 方法你可以自定义这个触发器。
```jsx live=true hideInDSM
import React, { useState, useMemo } from 'react';
import * as dateFns from 'date-fns';
import { TimePicker, Button } from '@douyinfe/semi-ui';
import { IconChevronDown, IconClose } from '@douyinfe/semi-icons';
function Demo() {
const formatToken = 'HH:mm:ss';
const [time, setTime] = useState(new Date());
return (
<TimePicker
value={time}
format={formatToken}
onChange={time => setTime(time)}
triggerRender={({ placeholder }) => (
<Tag
color='cyan'
size='large'
shape='circle'
style={{ padding: 12, paddingRight: 16, fontSize: 14 }}
theme={'light'}
prefixIcon={<IconTimePicker />}
>
{time ? dateFns.format(time, formatToken) : placeholder}
</Tag>
)}
/>
);
}
```
## 时区设置
Semi 所有关于时区的配置都收敛在 ConfigProvider 中,详细使用可以参考 [ConfigProvider](/zh-CN/other/configprovider)
```jsx live=true hideInDSM
import React, { useMemo, useState } from 'react';
import { ConfigProvider, Select, TimePicker } from '@douyinfe/semi-ui';
function Demo(props = {}) {
const [timeZone, setTimeZone] = useState('GMT+08:00');
const defaultTimestamp = 1581599305265;
const gmtList = useMemo(() => {
const list = [];
for (let hourOffset = -11; hourOffset <= 14 ; hourOffset++) {
const prefix = hourOffset >= 0 ? '+' : '-';
const hOffset = Math.abs(parseInt(hourOffset, 10));
list.push(`GMT${prefix}${String(hOffset).padStart(2, '0')}:00`);
}
return list;
}, []);
return (
<ConfigProvider timeZone={timeZone}>
<div style={{ width: 300 }}>
<h5 style={{ margin: 10 }}>Select Time Zone:</h5>
<Select
placeholder={'请选择时区'}
style={{ width: 300 }}
value={timeZone}
showClear={true}
onSelect={value => setTimeZone(value)}
>
{gmtList.map(gmt => (
<Select.Option key={gmt} value={gmt}>
{gmt}
</Select.Option>
))}
</Select>
<br/>
<br/>
<h5 style={{ margin: 10 }}>TimePicker:</h5>
<TimePicker defaultValue={defaultTimestamp} onChange={(date, dateString) => console.log('DatePicker changed: ', date, dateString)} />
</div>
</ConfigProvider>
);
}
```
## API 参考
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ---------- |
| autoAdjustOverflow | 浮层被遮挡时是否自动调整方向 | boolean | true | |
| autoFocus | 自动获取焦点 | boolean | false | |
| borderless | 无边框模式 >=2.33.0 | boolean | |
| className | 外层样式名 | string | | |
| clearIcon | 可用于自定义清除按钮, showClear为true时有效 | ReactNode | | **2.25.0** |
| defaultOpen | 面板是否默认打开 | boolean | | |
| defaultValue | 默认时间 | Date\|timeStamp\|String(type="timeRange"时为数组) | | |
| disabled | 禁用全部操作 | boolean | false | |
| disabledHours | 禁止选择部分小时选项 | Function(): number[] | | |
| disabledMinutes | 禁止选择部分分钟选项 | Function(selectedHour: number): number[] | | |
| disabledSeconds | 禁止选择部分秒选项 | Function(selectedHour: number, selectedMinute: number): number[] | | |
| disabledTime | **仅在 range 模式生效**:根据当前已选 dates 与面板位置返回 disabled 配置,左右面板可分别给出不同规则。回调参数 value:当前已选时间数组(length 0/1/2);panelType:`'left'` 或 `'right'`。返回值中存在的字段会**覆盖**对应的顶层 disabledHours / disabledMinutes / disabledSeconds,未返回的字段则**回退**到顶层(如需关闭顶层规则,请显式返回空数组的函数)。单选模式下该 prop 被忽略,请直接使用顶层 disabledHours / disabledMinutes / disabledSeconds | Function(value: Date[], panelType: 'left' \| 'right'): { disabledHours?: () => number[]; disabledMinutes?: (selectedHour: number) => number[]; disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[] } | | **2.97.0** |
| dropdownMargin | 浮层算溢出时的增加的冗余值,详见[issue#549](https://github.com/DouyinFE/semi-design/issues/549),作用同 Tooltip margin | object\|number | | **2.25.0** |
| focusOnOpen | 挂载时是否打开面板并focus输入框 | boolean | false | |
| format | 展示的时间格式 | string | "HH:mm:ss" | |
| getPopupContainer | 指定容器,浮层将会渲染至该元素内,自定义需要设置 `position: relative` 这会改变浮层 DOM 树位置,但不会改变视图渲染位置。 | Function(): HTMLElement | () => document.body | |
| hideDisabledOptions | 隐藏禁止选择的选项 | boolean | false | |
| hourStep | 小时选项间隔 | number | 1 | |
| inputReadOnly | 设置输入框为只读(避免在移动设备上打开虚拟键盘) | boolean | false | |
| minuteStep | 分钟选项间隔 | number | 1 | |
| motion | 是否展示弹出层动画 | boolean | true | |
| open | 面板是否打开的受控属性 | boolean | | |
| panelFooter | 面板底部 addon | ReactNode\|ReactNode[]\|string | 无 | |
| panelHeader | 面板头部 addon | ReactNode\|ReactNode[]\|string | 无 | |
| placeholder | 没有值的时候显示的内容 | string | "请选择时间" | |
| popupClassName | 弹出层类名 | string | '' | |
| popupStyle | 弹出层样式对象 | object | - | |
| position | 浮层位置 | string | type="timeRange"时默认为"bottom",type="time"时默认为"bottomLeft" | |
| prefix | 前缀内容 | string\|ReactNode | | |
| preventScroll | 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法 | boolean | | |
| rangeSeparator | 时间范围分隔符 | string | " ~ " | |
| scrollItemProps | 透传给 scrollItem 的属性,可选值同[ScrollList#API](/zh-CN/show/scrolllist#ScrollItem) | object | | |
| secondStep | 秒选项间隔 | number | 1 | |
| showClear | 是否展示清除按钮 | boolean | true | |
| stopPropagation | 是否阻止弹出层上的点击事件冒泡 | boolean | true | **2.49.0** |
| size | 输入框的大小,可选 'default','small','large' | string | 'default' | |
| triggerRender | 自定义触发器渲染方法 | ({ placeholder: string }) => ReactNode | - | |
| type | 类型 | "time"\|"timeRange" | "time" | |
| use12Hours | 使用 12 小时制,为 true 时 `format` 默认为 `h:mm:ss a` | boolean | false | |
| value | 当前时间 | Date\|timeStamp\|String(type="timeRange"时为数组) | | |
| onBlur | 失去焦点时的回调 | (e: domEvent) => void | () => {} | |
| onChange | 时间发生变化的回调 | Function(time: Date, timeString: string): void (type="timeRange"时入参皆为数组) | 无 | |
| onChangeWithDateFirst | 设置为 `true` 时 onChange 的入参顺序为 (Date, string), `false` 时为 (string, Date) | boolean | true | **2.4.0** |
| onFocus | 获得焦点时的回调 | (e: domEvent) => void | () => {} | |
| onOpenChange | 面板打开/关闭时的回调 | Function(isOpen: boolean): void | 无 | |
## Methods
绑定在组件实例上的方法,可以通过 ref 调用实现某些特殊交互
| 名称 | 描述 |
| ------- | -------- |
| blur() | 移除焦点 |
| focus() | 获取焦点 |
## 文案规范
- 时间选择器至少包括时和分,如:11:30,它在本地化过程中,可以适应为12小时制或者24小时制
- 当选择12小时制,需要和AM/PM一起搭配使用
## 设计变量
<DesignToken/>