Date Picker 日期选择器
用于选择日期。
选择某日
以「日」为粒度选择日期。
展示粒度由 type 决定。可通过 shortcuts 配置快捷项。disabled-date 为函数,用于禁用指定日期。
<template>
<u-radio-group v-model="size" aria-label="size control" class="mb-4">
<u-radio-button value="large">large</u-radio-button>
<u-radio-button value="default">default</u-radio-button>
<u-radio-button value="small">small</u-radio-button>
</u-radio-group>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">Default</span>
<u-date-picker
v-model="value1"
type="date"
placeholder="Pick a day"
:size="size"
/>
</div>
<div class="block">
<span class="demonstration">Picker with quick options</span>
<u-date-picker
v-model="value2"
type="date"
placeholder="Pick a day"
:disabled-date="disabledDate"
:shortcuts="shortcuts"
:size="size"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const size = ref<'default' | 'large' | 'small'>('default')
const value1 = ref('')
const value2 = ref('')
const shortcuts = [
{
text: 'Today',
value: new Date(),
},
{
text: 'Yesterday',
value: () => {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24)
return date
},
},
{
text: 'A week ago',
value: () => {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
return date
},
},
]
const disabledDate = (time: Date) => {
return time.getTime() > Date.now()
}
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
min-width: 300px;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
}
@media screen and (max-width: 768px) {
.demo-date-picker .block {
flex: 0 0 100%;
padding: 1rem 0;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
</style>
其他粒度
可在标准日期选择器上扩展为周、月、年或多选日期等类型。
<template>
<div class="demo-date-picker">
<div class="container">
<div class="block">
<span class="demonstration">Week</span>
<u-date-picker
v-model="value1"
type="week"
format="[Week] ww"
placeholder="Pick a week"
/>
</div>
<div class="block">
<span class="demonstration">Dates</span>
<u-date-picker
v-model="value2"
type="dates"
placeholder="Pick one or more dates"
/>
</div>
</div>
<div class="container">
<div class="block">
<span class="demonstration">Year</span>
<u-date-picker
v-model="value3"
type="year"
placeholder="Pick a year"
/>
</div>
<div class="block">
<span class="demonstration">Years</span>
<u-date-picker
v-model="value4"
type="years"
placeholder="Pick one or more years"
/>
</div>
</div>
<div class="container">
<div class="block">
<span class="demonstration">Month</span>
<u-date-picker
v-model="value5"
type="month"
placeholder="Pick a month"
/>
</div>
<div class="block">
<span class="demonstration">Months</span>
<u-date-picker
v-model="value6"
type="months"
placeholder="Pick one or more months"
/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value1 = ref('')
const value2 = ref('')
const value3 = ref('')
const value4 = ref('')
const value5 = ref('')
const value6 = ref('')
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .container {
flex: 1;
min-width: 300px;
border-right: solid 1px var(--u-border-color);
}
.demo-date-picker .container:last-child {
border-right: none;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
}
.demo-date-picker .container .block:last-child {
border-top: solid 1px var(--u-border-color);
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
}
@media screen and (max-width: 768px) {
.demo-date-picker .container {
flex: 0 0 100%;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .container:last-child {
border-bottom: none;
}
.demo-date-picker .block {
padding: 1rem 0;
}
.demo-date-picker .container .block:last-child {
border-top: solid 1px var(--u-border-color);
}
}
</style>
日期范围
支持选择起止日期。
范围模式下左右面板默认联动;若希望两侧月份独立切换,可使用 unlink-panels。
<template>
<u-radio-group v-model="size" aria-label="size control" class="mb-4">
<u-radio-button value="large">large</u-radio-button>
<u-radio-button value="default">default</u-radio-button>
<u-radio-button value="small">small</u-radio-button>
</u-radio-group>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">Default</span>
<u-date-picker
v-model="value1"
type="daterange"
range-separator="To"
start-placeholder="Start date"
end-placeholder="End date"
:size="size"
/>
</div>
<div class="block">
<span class="demonstration">With quick options</span>
<u-date-picker
v-model="value2"
type="daterange"
unlink-panels
range-separator="To"
start-placeholder="Start date"
end-placeholder="End date"
:shortcuts="shortcuts"
:size="size"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const size = ref<'default' | 'large' | 'small'>('default')
const value1 = ref('')
const value2 = ref('')
const shortcuts = [
{
text: 'Last week',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start, end]
},
},
{
text: 'Last month',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start, end]
},
},
{
text: 'Last 3 months',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start, end]
},
},
]
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
min-width: 400px;
display: flex;
flex-direction: column;
align-items: center;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
}
@media screen and (max-width: 1200px) {
.demo-date-picker .block {
flex: 0 0 100%;
padding: 1rem 0;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
</style>
月份范围
支持选择月份区间。
范围模式下左右面板默认联动;若希望两侧年份独立切换,可使用 unlink-panels。
<template>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">Default</span>
<u-date-picker
v-model="value1"
type="monthrange"
range-separator="To"
start-placeholder="Start month"
end-placeholder="End month"
/>
</div>
<div class="block">
<span class="demonstration">With quick options</span>
<u-date-picker
v-model="value2"
type="monthrange"
unlink-panels
range-separator="To"
start-placeholder="Start month"
end-placeholder="End month"
:shortcuts="shortcuts"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value1 = ref('')
const value2 = ref('')
const shortcuts = [
{
text: 'This month',
value: [new Date(), new Date()],
},
{
text: 'This year',
value: () => {
const end = new Date()
const start = new Date(new Date().getFullYear(), 0)
return [start, end]
},
},
{
text: 'Last 6 months',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 6)
return [start, end]
},
},
]
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
min-width: 300px;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
}
@media screen and (max-width: 768px) {
.demo-date-picker .block {
flex: 0 0 100%;
padding: 1rem 0;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
</style>
年份范围
支持选择年份区间。
范围模式下左右面板默认联动;若希望两侧年份独立切换,可使用 unlink-panels。
<template>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">Default</span>
<u-date-picker
v-model="value1"
type="yearrange"
range-separator="To"
start-placeholder="Start Year"
end-placeholder="End Year"
/>
</div>
<div class="block">
<span class="demonstration">With quick options</span>
<u-date-picker
v-model="value2"
type="yearrange"
unlink-panels
range-separator="To"
start-placeholder="Start Year"
end-placeholder="End Year"
:shortcuts="shortcuts"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value1 = ref()
const value2 = ref()
const shortcuts = [
{
text: 'This Year',
value: [new Date(), new Date()],
},
{
text: 'Last 10 years',
value: () => {
const end = new Date()
const start = new Date(
new Date().setFullYear(new Date().getFullYear() - 10)
)
return [start, end]
},
},
{
text: 'Next 50 years',
value: () => {
const start = new Date()
const end = new Date(
new Date().setFullYear(new Date().getFullYear() + 50)
)
return [start, end]
},
},
]
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
min-width: 300px;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
}
@media screen and (max-width: 768px) {
.demo-date-picker .block {
flex: 0 0 100%;
padding: 1rem 0;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
</style>
默认显示的月历
用户未选择时,日历默认定位到「今天」。可通过 default-value 指定其他日期,取值需能被 new Date() 解析。
当 type 为 daterange 时,default-value 作用于左侧日历。
<template>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">date</span>
<u-date-picker
v-model="value1"
type="date"
placeholder="Pick a date"
:default-value="new Date(2010, 9, 1)"
/>
</div>
<div class="block">
<span class="demonstration">daterange</span>
<u-date-picker
v-model="value2"
type="daterange"
start-placeholder="Start Date"
end-placeholder="End Date"
:default-value="[new Date(2010, 9, 1), new Date(2010, 10, 1)]"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value1 = ref('')
const value2 = ref('')
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
min-width: 300px;
display: flex;
flex-direction: column;
align-items: center;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
}
@media screen and (max-width: 768px) {
.demo-date-picker .block {
flex: 0 0 100%;
padding: 1rem 0;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
</style>
日期格式
使用 format 控制输入框内展示格式;使用 value-format 控制绑定值的格式。
未指定时,组件接受并向外抛出 Date 对象。
Day.js 可用占位符见官方列表。
WARNING
注意大小写。
<template>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">Emits Date object</span>
<div class="demonstration">Value: {{ value1 }}</div>
<u-date-picker
v-model="value1"
type="date"
placeholder="Pick a Date"
format="YYYY/MM/DD"
/>
</div>
<div class="block">
<span class="demonstration">Use value-format</span>
<div class="demonstration">Value:{{ value2 }}</div>
<u-date-picker
v-model="value2"
type="date"
placeholder="Pick a Date"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
/>
</div>
<div class="block">
<span class="demonstration">Timestamp</span>
<div class="demonstration">Value:{{ value3 }}</div>
<u-date-picker
v-model="value3"
type="date"
placeholder="Pick a Date"
format="YYYY/MM/DD"
value-format="x"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value1 = ref('')
const value2 = ref('')
const value3 = ref('')
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 1.5rem 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
min-width: 300px;
display: flex;
flex-direction: column;
align-items: center;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
width: 100%;
}
@media screen and (max-width: 1200px) {
.demo-date-picker .block {
flex: 0 0 50%;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:nth-child(2n) {
border-right: none;
}
.demo-date-picker .block:nth-last-child(-n + 2):nth-child(2n + 1),
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
@media screen and (max-width: 768px) {
.demo-date-picker .block {
flex: 0 0 100%;
padding: 1rem 0;
min-width: auto;
border-right: none;
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker .block:last-child {
border-bottom: none;
}
}
</style>
范围选择的默认时间
选择日期范围时,可为起止日期分别指定时间部分。
默认起止时间均为 00:00:00。default-time 为最多包含两个 Date 的数组:第一项作用于开始日期,第二项作用于结束日期。
Component value:
<template>
<div class="demo-date-picker">
<div class="block">
<p>Component value:{{ value }}</p>
<u-date-picker
v-model="value"
type="daterange"
start-placeholder="Start date"
end-placeholder="End date"
value-format="YYYY-MM-DD HH:mm:ss"
:default-time="defaultTime"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value = ref('')
const defaultTime = ref<[Date, Date]>([
new Date(2000, 1, 1, 0, 0, 0),
new Date(2000, 2, 1, 23, 59, 59),
])
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 30px 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
}
.demo-date-picker .block:last-child {
border-right: none;
}
</style>
自定义前缀内容
可自定义输入框前缀。
将 prefix-icon 设为你从其他 .vue 引入的组件,或由渲染函数生成的组件。
pre
<template>
<div class="demo-date-picker">
<div class="block">
<span class="demonstration">set prefix-icon</span>
<u-date-picker
v-model="value1"
type="date"
placeholder="Pick a day"
:prefix-icon="customPrefix"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { h, ref, shallowRef } from 'vue'
const value1 = ref('')
const customPrefix = shallowRef({
render() {
return h('p', 'pre')
},
})
</script>
<style scoped>
.demo-date-picker {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
}
.demo-date-picker .block {
padding: 30px 0;
text-align: center;
border-right: solid 1px var(--u-border-color);
flex: 1;
}
.demo-date-picker .block:last-child {
border-right: none;
}
.demo-date-picker .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 20px;
}
</style>
自定义单元格
单元格内容可通过作用域插槽自定义,可拿到单元格数据。自定义结构需与默认结构一致,否则可能出现样式错位。
<template>
<div class="demo-date-picker">
<u-date-picker
v-model="value"
type="date"
placeholder="Pick a day"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
>
<template #default="cell">
<div class="cell" :class="{ current: cell.isCurrent }">
<span class="text">{{ cell.text }}</span>
<span v-if="isHoliday(cell)" class="holiday" />
</div>
</template>
</u-date-picker>
<u-date-picker v-model="month" type="month" placeholder="Pick a month">
<template #default="cell">
<div class="u-date-table-cell" :class="{ current: cell.isCurrent }">
<span class="u-date-table-cell__text">{{ cell.text + 1 }}期</span>
</div>
</template>
</u-date-picker>
<u-date-picker v-model="year" type="year" placeholder="Pick a year">
<template #default="cell">
<div class="u-date-table-cell" :class="{ current: cell.isCurrent }">
<span class="u-date-table-cell__text">{{ cell.text + 1 }}y</span>
</div>
</template>
</u-date-picker>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const value = ref('2021-10-29')
const month = ref('')
const year = ref('')
const holidays = [
'2021-10-01',
'2021-10-02',
'2021-10-03',
'2021-10-04',
'2021-10-05',
'2021-10-06',
'2021-10-07',
]
const isHoliday = ({ dayjs }) => {
return holidays.includes(dayjs.format('YYYY-MM-DD'))
}
</script>
<style scoped>
.demo-date-picker {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.demo-date-picker > * {
margin: 0 !important;
}
.cell {
height: 30px;
padding: 3px 0;
box-sizing: border-box;
}
.cell .text {
width: 24px;
height: 24px;
display: block;
margin: 0 auto;
line-height: 24px;
position: absolute;
left: 50%;
transform: translateX(-50%);
border-radius: 50%;
}
.cell.current .text {
background: #626aef;
color: #fff;
}
.cell .holiday {
position: absolute;
width: 6px;
height: 6px;
background: var(--u-color-danger);
border-radius: 50%;
bottom: 0px;
left: 50%;
transform: translateX(-50%);
}
@media screen and (max-width: 768px) {
.demo-date-picker {
gap: 1.5rem;
}
}
</style>
自定义图标
可通过插槽替换导航等图标。
<template>
<div class="demo-date-picker-icon">
<div class="container">
<div class="block">
<div class="demonstration">date</div>
<u-date-picker
v-model="value1"
type="date"
placeholder="Pick a day"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
>
<template #prev-month>
<u-icon><CaretLeft /></u-icon>
</template>
<template #next-month>
<u-icon><CaretRight /></u-icon>
</template>
<template #prev-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M8.73171,16.7949 C9.03264,17.0795 9.50733,17.0663 9.79196,16.7654 C10.0766,16.4644 10.0634,15.9897 9.76243,15.7051 L4.52339,10.75 L17.2471,10.75 C17.6613,10.75 17.9971,10.4142 17.9971,10 C17.9971,9.58579 17.6613,9.25 17.2471,9.25 L4.52112,9.25 L9.76243,4.29275 C10.0634,4.00812 10.0766,3.53343 9.79196,3.2325 C9.50733,2.93156 9.03264,2.91834 8.73171,3.20297 L2.31449,9.27241 C2.14819,9.4297 2.04819,9.62981 2.01448,9.8386 C2.00308,9.89058 1.99707,9.94459 1.99707,10 C1.99707,10.0576 2.00356,10.1137 2.01585,10.1675 C2.05084,10.3733 2.15039,10.5702 2.31449,10.7254 L8.73171,16.7949 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
<template #next-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
</u-date-picker>
</div>
<div class="line" />
<div class="block">
<div class="demonstration">date range</div>
<u-date-picker
v-model="value2"
type="daterange"
start-placeholder="Start date"
end-placeholder="End date"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
unlink-panels
>
<template #prev-month>
<u-icon><CaretLeft /></u-icon>
</template>
<template #next-month>
<u-icon><CaretRight /></u-icon>
</template>
<template #prev-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M8.73171,16.7949 C9.03264,17.0795 9.50733,17.0663 9.79196,16.7654 C10.0766,16.4644 10.0634,15.9897 9.76243,15.7051 L4.52339,10.75 L17.2471,10.75 C17.6613,10.75 17.9971,10.4142 17.9971,10 C17.9971,9.58579 17.6613,9.25 17.2471,9.25 L4.52112,9.25 L9.76243,4.29275 C10.0634,4.00812 10.0766,3.53343 9.79196,3.2325 C9.50733,2.93156 9.03264,2.91834 8.73171,3.20297 L2.31449,9.27241 C2.14819,9.4297 2.04819,9.62981 2.01448,9.8386 C2.00308,9.89058 1.99707,9.94459 1.99707,10 C1.99707,10.0576 2.00356,10.1137 2.01585,10.1675 C2.05084,10.3733 2.15039,10.5702 2.31449,10.7254 L8.73171,16.7949 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
<template #next-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
</u-date-picker>
</div>
</div>
<div class="container">
<div class="line" />
<div class="block">
<div class="demonstration">month range</div>
<u-date-picker
v-model="value3"
type="monthrange"
start-placeholder="Start date"
end-placeholder="End date"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
unlink-panels
>
<template #prev-month>
<u-icon><CaretLeft /></u-icon>
</template>
<template #next-month>
<u-icon><CaretRight /></u-icon>
</template>
<template #prev-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M8.73171,16.7949 C9.03264,17.0795 9.50733,17.0663 9.79196,16.7654 C10.0766,16.4644 10.0634,15.9897 9.76243,15.7051 L4.52339,10.75 L17.2471,10.75 C17.6613,10.75 17.9971,10.4142 17.9971,10 C17.9971,9.58579 17.6613,9.25 17.2471,9.25 L4.52112,9.25 L9.76243,4.29275 C10.0634,4.00812 10.0766,3.53343 9.79196,3.2325 C9.50733,2.93156 9.03264,2.91834 8.73171,3.20297 L2.31449,9.27241 C2.14819,9.4297 2.04819,9.62981 2.01448,9.8386 C2.00308,9.89058 1.99707,9.94459 1.99707,10 C1.99707,10.0576 2.00356,10.1137 2.01585,10.1675 C2.05084,10.3733 2.15039,10.5702 2.31449,10.7254 L8.73171,16.7949 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
<template #next-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
</u-date-picker>
</div>
<div class="line" />
<div class="block">
<div class="demonstration">year range</div>
<u-date-picker
v-model="value4"
type="yearrange"
range-separator="To"
start-placeholder="Start Year"
end-placeholder="End Year"
>
<template #prev-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M8.73171,16.7949 C9.03264,17.0795 9.50733,17.0663 9.79196,16.7654 C10.0766,16.4644 10.0634,15.9897 9.76243,15.7051 L4.52339,10.75 L17.2471,10.75 C17.6613,10.75 17.9971,10.4142 17.9971,10 C17.9971,9.58579 17.6613,9.25 17.2471,9.25 L4.52112,9.25 L9.76243,4.29275 C10.0634,4.00812 10.0766,3.53343 9.79196,3.2325 C9.50733,2.93156 9.03264,2.91834 8.73171,3.20297 L2.31449,9.27241 C2.14819,9.4297 2.04819,9.62981 2.01448,9.8386 C2.00308,9.89058 1.99707,9.94459 1.99707,10 C1.99707,10.0576 2.00356,10.1137 2.01585,10.1675 C2.05084,10.3733 2.15039,10.5702 2.31449,10.7254 L8.73171,16.7949 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
<template #next-year>
<u-icon>
<svg
viewBox="0 0 20 20"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke-width="1" fill-rule="evenodd">
<g fill="currentColor">
<path
d="M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"
/>
</g>
</g>
</svg>
</u-icon>
</template>
</u-date-picker>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { CaretLeft, CaretRight } from '@uniboot/icons-vue'
const value1 = ref('')
const value2 = ref('')
const value3 = ref('')
const value4 = ref('')
</script>
<style scoped>
.demo-date-picker-icon {
display: flex;
width: 100%;
padding: 0;
flex-wrap: wrap;
gap: 1px;
}
.demo-date-picker-icon .container {
flex: 1;
min-width: 400px;
border-right: solid 1px var(--u-border-color);
display: flex;
flex-direction: column;
}
.demo-date-picker-icon .container:last-child {
border-right: none;
}
.demo-date-picker-icon .block {
padding: 1.5rem 0;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.demo-date-picker-icon .block:not(:first-child) {
border-top: solid 1px var(--u-border-color);
}
.demo-date-picker-icon .demonstration {
display: block;
color: var(--u-text-color-secondary);
font-size: 14px;
margin-bottom: 1rem;
width: 100%;
}
@media screen and (max-width: 1200px) {
.demo-date-picker-icon {
gap: 0;
}
.demo-date-picker-icon .container {
flex: 0 0 100%;
min-width: auto;
border-right: none;
}
.demo-date-picker-icon .container:not(:last-child) {
border-bottom: solid 1px var(--u-border-color);
}
.demo-date-picker-icon .block {
padding: 1rem 0;
}
.demo-date-picker-icon .block:not(:first-child) {
position: relative;
margin-top: -1px;
}
}
</style>
数据结构如下:
interface DateCell {
column: number
customClass: string | undefined
disabled: boolean
end: boolean
inRange: boolean
row: number
selected: Dayjs | undefined
isCurrent: boolean | undefined
isSelected: boolean
renderText: string | undefined
start: boolean
text: number
timestamp: number
date: Date
dayjs: Dayjs
type: 'normal' | 'today' | 'week' | 'next-month' | 'prev-month'
}国际化
默认语言为英文;若需其他语言请参考国际化。
日期时间相关的区域设置(月份名称、每周起始日等)也在语言包中配置。
API
属性
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 绑定值;范围选择时为长度 2 的数组 | number / string / Date / array | '' |
| readonly | 是否只读 | boolean | false |
| disabled | 是否禁用 | boolean | false |
| size | 输入框尺寸 | enum | — |
| editable | 文本框是否可编辑 | boolean | true |
| clearable | 是否显示清空按钮 | boolean | true |
| placeholder | 非范围模式下的占位符 | string | '' |
| start-placeholder | 范围模式下开始日期的占位符 | string | — |
| end-placeholder | 范围模式下结束日期的占位符 | string | — |
| type | 选择器类型 | enum | date |
| format | 输入框中展示值的格式 | string 参见日期格式 | YYYY-MM-DD |
| popper-class | 下拉面板的自定义类名 | string | — |
| popper-style | 下拉面板的自定义样式 | string / object | — |
| popper-options | Popper 配置,详见 popper.js | object | {} |
| range-separator | 范围分隔符 | string | '-' |
| default-value | 可选,日历默认定位的日期 | object | — |
| default-time | 可选,范围选择时默认的时间部分 | object | — |
| value-format | 可选,绑定值的格式;未指定时为 Date | string 参见日期格式 | — |
| id | 同原生 id | string / array | — |
| name | 同原生 name | string / array | '' |
| unlink-panels | 范围选择时是否解除左右面板联动 | boolean | false |
| prefix-icon | 自定义前缀图标;type 为时间类时默认为 Clock,否则为 Calendar | string / object | '' |
| clear-icon | 自定义清空图标 | string / object | CircleClose |
| validate-event | 是否触发表单校验 | boolean | true |
| disabled-date | 判断某日是否禁用的函数,参数为日期,返回布尔值 | Function | — |
| shortcuts | 快捷选项数组 | array | [] |
| cell-class-name | 为单元格设置自定义类名 | Function | — |
| teleported | 是否将弹层挂载到 body | boolean | true |
| empty-values | 视为空的取值,见 config-provider | array | — |
| value-on-clear | 清空后的绑定值,见 config-provider | string / number / boolean / Function | — |
| fallback-placements | Tooltip 可能的位置,见 popper.js | array | ['bottom', 'top', 'right', 'left'] |
| placement | 下拉出现位置 | Placement | bottom |
| show-footer | 是否显示底部栏 | boolean | true |
| show-confirm | 是否显示确认按钮 | boolean | true |
| show-week-number | 是否显示周数 | boolean | false |
| automatic-dropdown | 输入框聚焦时是否自动展开面板(3.0 起默认值将改为 false) | boolean | true |
事件
| 名称 | 说明 | 类型 |
|---|---|---|
| change | 用户确认或点击外部关闭时触发 | Function |
| blur | 输入框失焦时触发 | Function |
| focus | 输入框聚焦时触发 | Function |
| clear | 点击清空时触发 | Function |
| calendar-change | 日历所选日期变化时触发,仅 range 模式 | Function |
| panel-change | 点击导航切换年月时触发 | Function |
| visible-change | 下拉显示/隐藏时触发 | Function |
插槽
| 名称 | 说明 |
|---|---|
| default | 自定义单元格内容 |
| range-separator | 自定义范围分隔符 |
| prev-month | 上一月图标 |
| next-month | 下一月图标 |
| prev-year | 上一年图标 |
| next-year | 下一年图标 |
暴露
| 名称 | 说明 | 类型 |
|---|---|---|
| focus | 聚焦组件 | Function |
| blur | 使组件失焦 | Function |
| handleOpen | 打开弹层 | Function |
| handleClose | 关闭弹层 | Function |
类型声明
展开类型声明
import type { Options as PopperOptions } from '@popperjs/core'
type TimeLikeType = 'datetime' | 'datetimerange'
type Placement =
| 'top'
| 'top-start'
| 'top-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'left'
| 'left-start'
| 'left-end'
| 'right'
| 'right-start'
| 'right-end'