DatePicker 日期选择
日期选择器,支持年月视图切换、范围限制与快捷选项,可选到时分秒。
基础用法
<script setup>
import { ref } from 'vue'
const date = ref(null)
</script>
<template>
<SrDatePicker v-model="date" placeholder="选择日期" />
</template>当前值:(未选)
值类型是字符串
v-model 的输入输出都是字符串(格式 YYYY-MM-DD),不是 Date 对象。
这样设计是为了解决一个很实际的问题:Date 过不了 JSON 序列化, 存到状态里再刷新就变成字符串,类型对不上。统一用字符串, 从表单到接口到本地存储都不需要转换。
需要 Date 对象时用 parseDate() 转一下:
import { parseDate } from '@starriver/ui'
const dateObj = parseDate(picked.value)范围限制
min / max 限制可选区间,超出范围的日期直接不可点击—— 比选完再报错好得多。
<SrDatePicker v-model="picked" min="2026-09-01" max="2026-09-30" />区间按「天」比较,忽略时分秒
范围限制的语义是「可选哪几天」。若带上时间,max 那天的后半天会因为 晚于该日零点而被排除,用户会觉得「明明在范围内却点不了」。
快捷选项
<script setup>
const shortcuts = [
{ text: '今天', value: () => new Date() },
{ text: '一周后', value: () => new Date(Date.now() + 7 * 86400000) },
{ text: '一个月后', value: () => new Date(Date.now() + 30 * 86400000) }
]
</script>
<template>
<SrDatePicker v-model="picked" :shortcuts="shortcuts" />
</template>value 是函数而非固定值——「今天」在页面打开时和几小时后是两天, 传固定值就会算错。
日期时间
show-time 开启时间选择。时间列是单列切换式的(点「时」展开时列表、 再点「分」切换),不是三列并排——窄屏下三列会把每列挤得放不下两位数。
<SrDatePicker v-model="picked" show-time time-precision="minute" />
<SrDatePicker v-model="picked" show-time time-precision="second" :time-step="5" />default-time 指定没选时间时的默认值(默认 00:00:00)。 把它设成当前时间通常更符合预期——用户选了日期直接确定, 拿到的往往是「今天零点」,而后端多半希望是「此刻」。
浮层位置
<SrDatePicker placement="bottom-start" />
<SrDatePicker placement="bottom-end" />面板同样会自动校正视口边缘:靠近窗口底部时向上展开。
尺寸与状态
<SrDatePicker v-model="picked" size="sm" />
<SrDatePicker v-model="picked" disabled />
<SrDatePicker v-model="picked" clearable />
<SrDatePicker v-model="picked" invalid />触发器是只读的
不能手动输入日期。手输要处理大小写、分隔符、补零、非法日期…… 而用户真正想做的通常只是选一个日期,输入框带来的麻烦远多于便利。
常见报错:打开面板时抛 ReferenceError
早期版本的 open() 里残留了一行对已删除函数 scrollAllColumns() 的调用, 只要打开一次面板就会抛错。这个函数在「三列时间改为单列切换」的重构中 被删掉了,但调用点漏删。
现已修复。若你在升级后仍遇到,请检查是否用的是旧版本。
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | null | null | 当前值,格式 YYYY-MM-DD |
placeholder | string | — | 占位文本 |
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸 |
disabled | boolean | false | 是否禁用 |
clearable | boolean | false | 是否可清空 |
invalid | boolean | false | 是否处于错误态 |
min / max | string | — | 可选区间(按天比较) |
showToday | boolean | true | 是否显示「今天」按钮 |
shortcuts | { text, value }[] | — | 快捷选项,value 为返回日期的函数 |
placement | 'bottom-start' | 'bottom-end' | 'bottom-start' | 面板对齐方式 |
showTime | boolean | false | 是否选择时间 |
timePrecision | 'hour' | 'minute' | 'second' | 'second' | 时间精度 |
timeStep | number | 1 | 时间列步长 |
defaultTime | string | '00:00:00' | 未选时间时的默认值 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | string | null | 日期变化 |
change | string | null | 同上(语义化事件) |
panelChange | Date | 面板切换年月时触发 |
无障碍
- 日期格子是
<button>语义,可键盘聚焦与选中 - 当前日期带
aria-current="date",选中项带aria-selected - 面板打开时焦点移入,
Esc关闭并把焦点还给触发器—— 这一点常被忽略,导致键盘用户关闭面板后焦点丢失、要重新 Tab 一路找回来