Skip to content

时间选择器 TimePicker ​

赞助

输入或选择时间的控件

何时使用 ​

  • 需要输入或选择时间时
  • 需要选择一段时间范围时(type 为 timerange)

基本使用 ​

点击 TimePicker 后可在浮层中选择或输入某一时间


v-model:value:绑定毫秒时间戳

v-model:formatted-value:绑定字符串,格式由 value-format 决定

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import { set } from 'date-fns'
/** 用例初始值:当日指定时刻的时间戳(毫秒) */
function initialTime(hour: number, minute: number = 0, second: number = 0): number {
  return set(new Date(), { hours: hour, minutes: minute, seconds: second, milliseconds: 0 }).getTime()
}
const basicValue = ref<number | null>(initialTime(8))
const basicFixedTextValue = ref<string | null>('09:00:00')
</script>
<template>
  <Space vertical>
    <p class="mb10"><code>v-model:value</code>:绑定毫秒时间戳</p>
    <TimePicker v-model:value="basicValue" placeholder="请选择时间" />
    <p class="mb10"><code>v-model:formatted-value</code>:绑定字符串,格式由 <code>value-format</code> 决定</p>
    <TimePicker v-model:formatted-value="basicFixedTextValue" value-format="HH:mm:ss" placeholder="请选择时间" />
  </Space>
</template>

附加内容 ​

在 TimePicker 选择框底部显示自定义的内容


绑定 v-model:open 并接收 openChange

只绑定 v-model:open(不接收 openChange)

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<number | null>(null)
const value2 = ref<number | null>(null)
const open = ref(false)
const open2 = ref(false)
function closePanel() {
  open.value = false
  open2.value = false
}
function onOpenChange(openState: boolean) {
  console.log('openChange', openState)
}
</script>
<template>
  <Space vertical>
    <p class="mb10">绑定 <code>v-model:open</code> 并接收 <code>openChange</code></p>
    <TimePicker v-model:value="value" v-model:open="open" placeholder="请选择时间" @open-change="onOpenChange">
      <template #renderExtraFooter>
        <Button size="small" type="primary" @click="closePanel">OK</Button>
      </template>
    </TimePicker>
    <p class="mb10">只绑定 <code>v-model:open</code>(不接收 <code>openChange</code>)</p>
    <TimePicker v-model:value="value2" v-model:open="open2" placeholder="请选择时间">
      <template #renderExtraFooter>
        <Button size="small" type="primary" @click="closePanel">OK</Button>
      </template>
    </TimePicker>
  </Space>
</template>

额外内容渲染在操作行之上、位于同一块面板区域内,因此不会横跨面板;页脚按钮由使用方自行控制浮层的展开与收起

12 小时制 ​

use12Hours 启用 12 小时制,默认的 format 为 hh:mm:ss a


默认 format(hh:mm:ss a):小时补零

显式 format="h:mm:ss a":小时不补零

显式 format="h:mm a":只到分(面板只有时 / 分两列)

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const h12Value = ref<number | null>(null)
const h12FormatValue = ref<number | null>(null)
const h12ShortValue = ref<number | null>(null)
</script>
<template>
  <Space vertical>
    <p class="mb10">默认 <code>format</code>(<code>hh:mm:ss a</code>):小时补零</p>
    <TimePicker v-model:value="h12Value" use12-hours placeholder="请选择时间" />
    <p class="mb10">显式 <code>format="h:mm:ss a"</code>:小时不补零</p>
    <TimePicker v-model:value="h12FormatValue" use12-hours format="h:mm:ss a" placeholder="请选择时间" />
    <p class="mb10">显式 <code>format="h:mm a"</code>:只到分(面板只有时 / 分两列)</p>
    <TimePicker v-model:value="h12ShortValue" use12-hours format="h:mm a" placeholder="请选择时间" />
  </Space>
</template>

禁用 ​

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import { set } from 'date-fns'
const disabledValue = ref<number | null>(set(new Date(), { hours: 12, minutes: 8, seconds: 23, milliseconds: 0 }).getTime())
</script>
<template>
  <TimePicker v-model:value="disabledValue" disabled placeholder="请选择时间" />
</template>

选择时分 ​

浮层中的列随 format 变化,略去其中某一部分时对应的列随之消失


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import { set } from 'date-fns'
const hourMinuteValue = ref<number | null>(set(new Date(), { hours: 12, minutes: 8, seconds: 0, milliseconds: 0 }).getTime())
</script>
<template>
  <TimePicker v-model:value="hourMinuteValue" format="HH:mm" placeholder="请选择时间" />
</template>

步长选项 ​

使用 hourStep minuteStep secondStep 按步长展示可选的时分秒


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const intervalValue = ref<number | null>(null)
const intervalMinuteStep = 15
const intervalSecondStep = 10
</script>
<template>
  <TimePicker
    v-model:value="intervalValue"
    :minute-step="intervalMinuteStep"
    :second-step="intervalSecondStep"
    placeholder="请选择时间"
  />
</template>

三种大小 ​

三种大小的输入框,大的用在表单中,中的为默认


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import { set } from 'date-fns'
const sizeValue = ref<number | null>(set(new Date(), { hours: 12, minutes: 8, seconds: 23, milliseconds: 0 }).getTime())
</script>
<template>
  <Space vertical>
    <TimePicker v-model:value="sizeValue" size="large" placeholder="请选择时间" />
    <TimePicker v-model:value="sizeValue" placeholder="请选择时间" />
    <TimePicker v-model:value="sizeValue" size="small" placeholder="请选择时间" />
  </Space>
</template>

后缀图标 ​

通过 suffixIcon 插槽自定义选择框后缀图标


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
import { SmileOutlined } from '@ant-design/icons-vue'
const suffixValue = ref<number | null>(null)
</script>
<template>
  <TimePicker v-model:value="suffixValue" placeholder="请选择时间">
    <template #suffixIcon>
      <SmileOutlined />
    </template>
  </TimePicker>
</template>

受控组件 ​

value 和 @change 需要配合使用,也可以直接使用 v-model


使用 value 和 @change

使用 v-model

只传 value 不回写(不响应变更)

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const controlledValue = ref<number | null>(null)
const fixedValue = ref<number | null>(new Date().getTime())
function onControlledChange(
  value: number | [number | null, number | null] | null,
  formattedValue: string | [string, string] | null
): void {
  console.log('onChange', value, formattedValue)
  controlledValue.value = typeof value === 'number' ? value : null
}
</script>
<template>
  <Space vertical>
    <p class="mb10">使用 <code>value</code> 和 <code>@change</code></p>
    <TimePicker :value="controlledValue" placeholder="请选择时间" @change="onControlledChange" />
    <p class="mb10">使用 <code>v-model</code></p>
    <TimePicker v-model:value="controlledValue" placeholder="请选择时间" />
    <p class="mb10">只传 <code>value</code> 不回写(不响应变更)</p>
    <TimePicker :value="fixedValue" placeholder="请选择时间" />
  </Space>
</template>

范围选择器 ​

type 为 timerange 时使用时间范围选择器


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const rangeValue = ref<[number | null, number | null] | null>(null)
const rangePlaceholder: [string, string] = ['开始时间', '结束时间']
</script>
<template>
  <TimePicker v-model:value="rangeValue" type="timerange" :placeholder="rangePlaceholder" />
</template>

范围形态的两段共用同一个时间面板,点「确定」提交当前段并自动切到另一端,两段都确定后才收起;展开期间的选择只落在草稿上,关闭面板则丢弃草稿。起点晚于终点时丢弃另一端;配合 allowEmpty 可放行单段区间,配合 disabledTime 可按段禁用时分秒

事件 ​

单选形态绑定 change、ok、openChange、focus、blur,范围形态绑定 change、calendarChange、ok、openChange;各事件的参数都会打印到控制台


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const eventValue = ref<number | null>(null)
const eventRangeValue = ref<[number | null, number | null] | null>(null)
const rangePlaceholder: [string, string] = ['开始时间', '结束时间']
/** 值变化时的回调:值与格式化值双轨 */
function onEventChange(
  value: number | [number | null, number | null] | null,
  formattedValue: string | [string, string] | null
): void {
  console.log('change', value, formattedValue)
}
/** 范围形态待选段变化时的回调:`info.range` 标识本次改动落在哪一段 */
function onEventCalendarChange(
  value: number | [number | null, number | null] | null,
  formattedValue: string | [string, string] | null,
  info: { range: 'start' | 'end' }
): void {
  console.log('calendarChange', value, formattedValue, info)
}
/** 点击「确定」时的回调(「此刻」是快捷入口,不派发) */
function onEventOk(
  value: number | [number | null, number | null] | null,
  formattedValue: string | [string, string] | null
): void {
  console.log('ok', value, formattedValue)
}
/** 面板展开收起时的回调 */
function onEventOpenChange(open: boolean): void {
  console.log('openChange', open)
}
/** 输入框获取焦点时的回调 */
function onEventFocus(event: FocusEvent): void {
  console.log('focus', event)
}
/** 输入框失去焦点时的回调 */
function onEventBlur(event: FocusEvent): void {
  console.log('blur', event)
}
</script>
<template>
  <Space vertical>
    <TimePicker
      v-model:value="eventValue"
      placeholder="请选择时间"
      @change="onEventChange"
      @ok="onEventOk"
      @open-change="onEventOpenChange"
      @focus="onEventFocus"
      @blur="onEventBlur"
    />
    <TimePicker
      v-model:value="eventRangeValue"
      type="timerange"
      :placeholder="rangePlaceholder"
      @change="onEventChange"
      @calendar-change="onEventCalendarChange"
      @ok="onEventOk"
      @open-change="onEventOpenChange"
    />
  </Space>
</template>

无边框 ​

Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const borderedValue = ref<number | null>(null)
const borderedRangeValue = ref<[number | null, number | null] | null>(null)
const rangePlaceholder: [string, string] = ['开始时间', '结束时间']
</script>
<template>
  <Space vertical>
    <TimePicker v-model:value="borderedValue" :bordered="false" placeholder="请选择时间" />
    <TimePicker
      v-model:value="borderedRangeValue"
      type="timerange"
      :bordered="false"
      :placeholder="rangePlaceholder"
    />
  </Space>
</template>

自定义状态 ​

使用 status 添加校验状态,可选 error 与 warning


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const errorValue = ref<number | null>(null)
const warningValue = ref<number | null>(null)
const errorRangeValue = ref<[number | null, number | null] | null>(null)
const warningRangeValue = ref<[number | null, number | null] | null>(null)
const rangePlaceholder: [string, string] = ['开始时间', '结束时间']
</script>
<template>
  <Space vertical>
    <TimePicker v-model:value="errorValue" status="error" placeholder="请选择时间" />
    <TimePicker v-model:value="warningValue" status="warning" placeholder="请选择时间" />
    <TimePicker v-model:value="errorRangeValue" type="timerange" status="error" :placeholder="rangePlaceholder" />
    <TimePicker
      v-model:value="warningRangeValue"
      type="timerange"
      status="warning"
      :placeholder="rangePlaceholder"
    />
  </Space>
</template>

弹出位置 ​

通过 placement 手动指定弹出的位置


Show Code
vue
<script setup lang="ts">
import { ref } from 'vue'
const placementBottomLeftValue = ref<number | null>(null)
const placementBottomRightValue = ref<number | null>(null)
const placementTopLeftValue = ref<number | null>(null)
const placementTopRightValue = ref<number | null>(null)
const placementRangeBottomLeftValue = ref<[number | null, number | null] | null>(null)
const placementRangeTopLeftValue = ref<[number | null, number | null] | null>(null)
const rangePlaceholder: [string, string] = ['开始时间', '结束时间']
</script>
<template>
  <Space vertical>
    <TimePicker v-model:value="placementBottomLeftValue" placement="bottomLeft" placeholder="左下" />
    <TimePicker v-model:value="placementBottomRightValue" placement="bottomRight" placeholder="右下" />
    <TimePicker v-model:value="placementTopLeftValue" placement="topLeft" placeholder="左上" />
    <TimePicker v-model:value="placementTopRightValue" placement="topRight" placeholder="右上" />
    <TimePicker
      v-model:value="placementRangeBottomLeftValue"
      type="timerange"
      placement="bottomLeft"
      :placeholder="rangePlaceholder"
    />
    <TimePicker
      v-model:value="placementRangeTopLeftValue"
      type="timerange"
      placement="topLeft"
      :placeholder="rangePlaceholder"
    />
  </Space>
</template>

APIs ​

TimePicker ​

参数说明类型默认值
value
v-model
双向绑定值,毫秒时间戳;范围形态为两段元组TimePickerValuenull
formattedValue
v-model
字符串轨道的双向绑定值,传入时以它为准(受控);显示格式由 format / valueFormat 决定TimePickerFormattedValuenull
open
v-model
面板是否展开booleanfalse
type选择形态:time 为单选,timerange 为范围(双段输入)TimePickerType'time'
format时间展示格式,参考 formatstringDefaultFormat
valueFormat绑定值格式,默认与 format 相同stringundefined
placeholder输入框提示文字,范围形态可分别为两段指定string | [string, string]''
disabledTime不可选择的时间,入参为当前面板值的时间戳;范围形态追加当前段标识TimePickerDisabledTimeundefined
hourStep「时」的步长,须能整除 24,否则按 1 处理number1
minuteStep「分」的步长,须能整除 60,否则按 1 处理number1
secondStep「秒」的步长,须能整除 60,否则按 1 处理number1
use12Hours是否使用 12 小时制,启用后面板追加上午 / 下午列,默认 format 为 hh:mm:ss abooleanfalse
hideDisabledOptions是否隐藏禁用的选项booleanfalse
width选择器宽度,单位 px,不传时随内容自适应string | numberundefined
size选择器大小'small' | 'middle' | 'large''middle'
status校验状态'warning' | 'error'undefined
bordered是否展示边框booleantrue
disabled是否禁用,范围形态可传两段元组逐段禁用boolean | [boolean, boolean]false
allowClear是否展示清除按钮booleantrue
allowEmpty范围形态各段是否允许为空,为空时该段可被单独清空并对外提交[boolean, boolean][false, false]
inputReadOnly输入框是否只读(避免移动端唤起键盘)booleanfalse
to面板挂载的容器节点:显式传入时按此挂载(元素标签名 (例如 'body') 或元素本身,false 会待在原地);不传时优先挂到最近的承载层内容容器(Modal / Drawer / Dialog 卡片或上层浮层面板),无承载层时为 bodystring | HTMLElement | falseundefined
placement面板弹出位置'topLeft' | 'top' | 'topRight' | 'bottomLeft' | 'bottom' | 'bottomRight''bottomLeft'
showArrow范围形态的面板指示箭头是否展示:不传时跟随弹出方位(仅左侧对齐的 bottomLeft / topLeft 展示),true 始终展示、false 始终隐藏booleanundefined
showNow是否展示面板底部的「此刻」快捷,仅单选形态生效booleantrue
renderExtraFooter面板底部的额外页脚,渲染在操作行之上() => VNode | VNode[]undefined
suffixIcon自定义选择框后缀图标VNode | (() => VNode)undefined
panelClass面板额外类名string''
panelStyle面板额外样式CSSPropertiesundefined
zIndex面板层级,优先级最高(覆盖默认层级与 ConfigProvider 的 baseZIndex 自动分配)numberundefined

时间面板的选择只落在草稿值上:点时间列不落值,点「确定」才提交并收起面板,收起(点击外部 / Esc)则丢弃未确认的选择;「此刻」是取当前时刻并按步长向下取整后直接提交的快捷入口(仅单选形态)。

TimePickerType Type ​

名称说明类型默认值
TimePickerType选择形态'time' | 'timerange''time'

TimePickerValue Type ​

名称说明类型默认值
TimePickerValue双向绑定值,毫秒时间戳;范围形态为两段元组number | [number | null, number | null] | nullnull

TimePickerFormattedValue Type ​

名称说明类型默认值
TimePickerFormattedValue字符串轨道的双向绑定值,格式由 valueFormat 决定;范围形态两段未选时分别为空字符串string | [string, string] | nullnull

TimePickerDisabledTime Type ​

名称说明类型默认值
TimePickerDisabledTime不可选择的时间判定(范围形态的判定额外接收当前段标识)(timestamp: number, side?: TimePickerRangeSide) => TimePickerDisabledTimeUnitsundefined

TimePickerRangeSide Type ​

名称说明类型默认值
TimePickerRangeSide范围形态的段标识'start' | 'end'undefined

TimePickerRangeInfo Type ​

名称说明类型默认值
TimePickerRangeInfo范围形态草稿变更的来源信息{ range: TimePickerRangeSide }undefined

TimePickerDisabledTimeUnits Type ​

名称说明类型默认值
disabledHours禁用的「时」() => number[]undefined
disabledMinutes禁用的「分」,入参为选中的「时」(hour: number) => number[]undefined
disabledSeconds禁用的「秒」,入参为选中的「时」「分」(hour: number, minute: number) => number[]undefined

DefaultFormat Value ​

类型值
24 小时制'HH:mm:ss'
12 小时制(use12Hours)'hh:mm:ss a'

format 支持的格式化占位符列表 ​

format / valueFormat 采用 date-fns 占位符,时间相关占位符:

标识示例描述
h1-12小时,12 小时制
hh01-12小时,12 小时制,两位数
H0-23小时
HH00-23小时,两位数
m0-59分钟
mm00-59分钟,两位数
s0-59秒
ss00-59秒,两位数
aAM上午 / 下午标记

面板列的显隐由 format 推导:格式中含 s / m / H·h 才展示对应列,含 a 则启用 12 小时制(显式传入的 use12Hours 优先)。

Slots ​

名称说明用法
suffixIcon自定义选择框后缀图标,优先于同名属性v-slot:suffixIcon
separator范围形态两段之间的分隔符,默认右向箭头v-slot:separator
renderExtraFooter面板底部的额外页脚,渲染在操作行之上,优先于同名属性v-slot:renderExtraFooter

Methods ​

名称说明类型
focus使选择器获取焦点() => void
blur使选择器失去焦点() => void

Events ​

名称说明类型
change值变化时的回调(value: TimePickerValue, formattedValue: TimePickerFormattedValue) => void
calendarChange范围形态草稿段变更时的回调,info.range 标注本次改动的段(value: TimePickerValue, formattedValue: TimePickerFormattedValue, info: TimePickerRangeInfo) => void
ok点击「确定」时的回调(value: TimePickerValue, formattedValue: TimePickerFormattedValue) => void
openChange面板展开收起时的回调(open: boolean) => void
focus输入框获取焦点时的回调(event: FocusEvent) => void
blur输入框失去焦点时的回调(event: FocusEvent) => void

Released under the MIT License.