一、uView Pro 的 Calendar 组件
在 uni-app 开发中,日期选择是一个高频需求场景。无论是酒店预订的入住离店时间选择、电商平台的商品预约、还是日常应用的打卡签到,一个功能完善、体验优秀的日历组件都是必不可少的。
uView Pro 作为 uni-app 生态中备受关注的 Vue3 组件库,其 Calendar 日历组件 经过了多个版本的迭代优化,从最初的基础日期选择,逐步演进为支持农历显示、打卡签到、节假日标记、自定义价格日历等丰富功能的综合型组件。
本文将深入解析 uView Pro Calendar 组件的核心特性、实现原理以及实际应用场景,帮助你快速掌握这个强大的日期选择利器。
二、组件概览:功能特性总览

uView Pro 的 Calendar 日历组件具有以下核心特性:
基础功能
- ✅ 支持单日期选择和日期范围选择两种模式
- ✅ 底部弹窗和页面嵌入两种展示方式
- ✅ 年月切换导航,支持自定义年份范围
- ✅ 日期范围限制,防止选择无效日期
进阶功能
- ✅ 农历显示支持,自动计算农历日期
- ✅ 打卡签到模式,支持已打卡/未打卡状态展示
- ✅ 节假日和加班日标记,显示"休"/"班"标识
- ✅ 内置中国传统节日,支持自定义节日配置
- ✅ 自定义日期内容插槽,适用于价格日历等场景
交互优化
- ✅ 默认选中今天,支持指定默认日期
- ✅ 只读模式,禁止日期选择
- ✅ 选中效果可配置,适应不同视觉需求
三、基础使用:快速上手
3.1 单日期选择模式
单日期选择是最常用的场景,比如选择生日、预约日期等。

<template>
<view>
<u-calendar v-model="show" mode="date" @change="onChange"></u-calendar>
<u-button @click="show = true">选择日期</u-button>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CalendarChangeDate } from 'uview-pro/types/global'
const show = ref(false)
function onChange(e: CalendarChangeDate) {
console.log('选择的日期:', e.result)
console.log('星期:', e.week)
console.log('是否今天:', e.isToday)
}
</script>
回调参数说明:
| 属性 |
说明 |
类型 |
| year |
选择的年份 |
number |
| month |
选择的月份 |
number |
| day |
选择的日期 |
number |
| result |
格式化的日期字符串,如 "2024-06-15" |
string |
| week |
星期文字,如 "星期六" |
string |
| isToday |
是否选择了今天 |
boolean |
3.2 日期范围选择模式
范围选择适用于酒店预订、行程规划等需要起止时间的场景。

<template>
<u-calendar
v-model="show"
mode="range"
start-text="入住"
end-text="离店"
@change="onRangeChange"
>
<template #tooltip>
<view class="tip">请选择入住和离店时间</view>
</template>
</u-calendar>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CalendarChangeRange } from 'uview-pro/types/global'
const show = ref(false)
function onRangeChange(e: CalendarChangeRange) {
console.log('入住日期:', e.startDate)
console.log('离店日期:', e.endDate)
console.log('共', e.endDay - e.startDay + 1, '晚')
}
</script>
范围模式回调参数:
| 属性 |
说明 |
| startDate / endDate |
起始/结束日期字符串 |
| startYear / endYear |
起始/结束年份 |
| startMonth / endMonth |
起始/结束月份 |
| startDay / endDay |
起始/结束日期 |
| startWeek / endWeek |
起始/结束星期 |
四、进阶功能详解
4.1 农历显示
Calendar 组件内置了农历计算功能,开启后会自动显示农历日期。

<u-calendar
v-model="show"
mode="date"
:show-lunar="true"
@change="onLunarChange"
></u-calendar>
开启农历后,回调参数会增加 lunar 对象:
{
day: 15,
month: 6,
result: "2024-06-15",
lunar: {
dayCn: '初十', // 农历日
monthCn: '五月', // 农历月
year: 2024, // 农历年
weekCn: "星期六" // 农历星期
}
}
农历显示会自动处理闰月、大小月等复杂逻辑,无需开发者关心底层实现。
4.2 页面嵌入模式
除了弹窗模式,组件还支持直接嵌入页面显示,适用于需要常驻展示日历的场景。
<template>
<view class="calendar-page">
<u-calendar
:is-page="true"
mode="date"
@change="onChange"
></u-calendar>
</view>
</template>
页面模式的特点:
- 不显示弹窗和确定按钮
- 选择日期后自动触发
change 事件
- 支持所有其他功能(农历、打卡、节假日等)

4.3 打卡签到模式
打卡签到日历也是近期咨询我比较多的功能,Calendar 组件专门为此设计了打卡模式。

<template>
<u-calendar
:is-page="true"
:checkin-mode="true"
:checked-dates="checkedDates"
:today-checked="todayChecked"
></u-calendar>
</template>
<script setup>
import { ref } from 'vue'
// 已打卡日期列表
const checkedDates = ref([
'2024-01-01',
'2024-01-02',
'2024-01-03',
'2024-01-05'
])
// 今日打卡状态(优先级高于自动判断)
const todayChecked = ref(true)
</script>
打卡模式的显示规则:
-
今日已打卡:绿色圆形背景,显示白色对勾
-
其他已打卡日期:橙色圆形背景,显示日期
-
未打卡日期(
checkin-mode 为 true 时):灰色圆形背景
颜色自定义:
| 属性 |
说明 |
默认值 |
| checked-bg-color |
已打卡日期背景色 |
橙色(warning) |
| today-checked-bg-color |
今日已打卡背景色 |
绿色(success) |
| unchecked-bg-color |
未打卡日期背景色 |
灰色(light) |
4.4 节假日与加班日标记
组件支持显示节假日和加班日标记,方便用户了解日期属性。
<template>
<u-calendar
:is-page="true"
:holidays="holidays"
:workdays="workdays"
></u-calendar>
</template>
<script setup>
import { ref } from 'vue'
// 节假日(元旦假期)
const holidays = ref(['2024-01-01', '2024-01-02'])
// 加班日(调休上班)
const workdays = ref(['2024-01-06', '2024-01-07'])
</script>
显示效果:
- 节假日:日期右上角显示红色"休"字
- 加班日:日期右上角显示蓝色"班"字
- 选中状态下,"休"/"班"字变为白色

4.5 节日显示
组件内置了中国传统节日,同时支持自定义节日配置。
内置节日(show-festival 为 true 时自动显示):
- 元旦(1月1日)
- 情人节(2月14日)
- 妇女节(3月8日)
- 植树节(3月12日)
- 愚人节(4月1日)
- 劳动节(5月1日)
- 青年节(5月4日)
- 儿童节(6月1日)
- 建党节(7月1日)
- 建军节(8月1日)
- 教师节(9月10日)
- 国庆节(10月1日)
- 光棍节(11月11日)
- 圣诞节(12月25日)
自定义节日:
<template>
<u-calendar
:is-page="true"
:show-festival="true"
:festivals="customFestivals"
></u-calendar>
</template>
<script setup>
import { ref } from 'vue'
const customFestivals = ref({
// 每年固定节日(MM-DD 格式)
'04-04': '清明节',
'05-05': '端午节',
'08-15': '中秋节',
// 特定年份节日(YYYY-MM-DD 格式)- 优先级更高
'2025-04-04': '清明节(2025)',
// 覆盖内置节日(传入空字符串不显示)
'02-14': '',
})
</script>
优先级规则:
- 特定年份格式(
YYYY-MM-DD)优先级最高
- 每年固定格式(
MM-DD)次之
- 内置节日优先级最低
4.6 自定义日期内容:价格日历
通过 date 插槽,可以完全自定义每个日期的显示内容,常用于电商价格日历场景。

<template>
<u-calendar
:is-page="true"
mode="date"
:use-date-slot="true"
>
<template #date="{ date }">
<text :class="getPriceClass(date)">
{{ getPriceText(date) }}
</text>
</template>
</u-calendar>
</template>
<script setup>
import { ref } from 'vue'
// 价格数据
const priceMap = ref({
'2024-01-01': 299,
'2024-01-02': 399,
'2024-01-03': 359,
// ...
})
function getPriceText(date) {
if (date.isToday) return '今天'
const price = priceMap.value[date.date]
return price ? `¥${price}` : ''
}
function getPriceClass(date) {
if (date.isSelected) return 'price-selected'
if (date.isToday) return 'price-today'
return 'price-normal'
}
</script>
<style scoped>
.price-today {
color: #19be6b;
font-weight: bold;
}
.price-normal {
color: #909399;
font-size: 22rpx;
}
.price-selected {
color: #ffffff;
}
</style>
插槽作用域参数:
| 属性 |
说明 |
类型 |
| date.year |
年份 |
number |
| date.month |
月份 |
number |
| date.day |
日期 |
number |
| date.date |
完整日期字符串 |
string |
| date.week |
星期文字 |
string |
| date.isToday |
是否今天 |
boolean |
| date.isHoliday |
是否节假日 |
boolean |
| date.isWorkday |
是否加班日 |
boolean |
| date.isChecked |
是否已打卡 |
boolean |
| date.isSelected |
是否选中 |
boolean |
| date.lunar |
农历信息 |
object |
五、核心实现原理浅析
5.1 日历渲染逻辑
Calendar 组件的日历渲染基于以下核心算法:
// 获取某月天数
function getMonthDay(year: number, month: number) {
return new Date(year, month, 0).getDate()
}
// 获取某月第一天星期几(0-6)
function getWeekday(year: number, month: number) {
let date = new Date(`${year}/${month}/01 00:00:00`)
return date.getDay()
}
渲染流程:
- 计算当月第一天是星期几,生成前置空白格子
- 计算当月总天数,生成日期格子
- 根据选中状态计算每个格子的样式
- 如果有农历,调用农历转换库计算农历日期
5.2 农历计算
组件使用了独立的农历计算工具 Calendar.solar2lunar,将公历日期转换为农历:
function getLunar(year: any, month: any, day: any) {
const val = Calendar.solar2lunar(year, month, day)
return {
dayCn: val.IDayCn, // 农历日(初十、廿三等)
monthCn: val.IMonthCn, // 农历月(正月、五月等)
weekCn: val.ncWeek, // 农历星期
day: val.lDay, // 农历日数字
month: val.lMonth, // 农历月数字
year: val.lYear // 农历年
}
}
5.3 范围选择逻辑
范围选择采用两次点击确定起止时间的交互方式:
function dateClick(dayIdx: number) {
const d = dayIdx + 1
const date = `${year.value}-${month.value}-${d}`
if (props.mode == 'range') {
// 判断是设置开始日期还是结束日期
const compare = new Date(date).getTime() < new Date(startDate.value).getTime()
if (isStart.value || compare) {
// 设置开始日期
startDate.value = date
isStart.value = false
} else {
// 设置结束日期
endDate.value = date
isStart.value = true
// 触发回调
if (props.isPage) btnFix(true)
}
}
}
六、实际应用场景
6.1 酒店预订日历
<u-calendar
v-model="show"
mode="range"
start-text="入住"
end-text="离店"
:min-date="minDate"
:max-date="maxDate"
@change="onDateChange"
>
<template #tooltip>
<view class="hotel-tip">
<text>请选择入住和离店日期</text>
<text class="sub">入住时间14:00后,离店时间12:00前</text>
</view>
</template>
</u-calendar>
6.2 健身打卡应用
<u-calendar
:is-page="true"
:checkin-mode="true"
:checked-dates="monthCheckins"
:today-checked="todayChecked"
:show-lunar="true"
@change="onCheckin"
></u-calendar>
6.3 航班价格日历
<u-calendar
:is-page="true"
mode="date"
:use-date-slot="true"
:default-select-today="false"
:is-active-current="false"
>
<template #date="{ date }">
<view class="flight-price">
<text class="day">{{ date.day }}</text>
<text class="price" v-if="getPrice(date.date)">
¥{{ getPrice(date.date) }}
</text>
</view>
</template>
</u-calendar>
6.4 日程管理应用
<u-calendar
:is-page="true"
:show-festival="true"
:festivals="customFestivals"
:holidays="holidays"
:workdays="workdays"
:default-date="selectedDate"
@change="onSelectDate"
></u-calendar>
七、API 完整参考
Props 属性
| 参数 |
说明 |
类型 |
默认值 |
| v-model |
控制弹窗显示/隐藏 |
boolean |
false |
| mode |
选择模式:date 单选 / range 范围 |
string |
date |
| is-page |
是否在页面中直接显示 |
boolean |
false |
| show-lunar |
是否显示农历 |
boolean |
false |
| readonly |
是否只读 |
boolean |
false |
| default-date |
默认选中日期(单选模式) |
string |
- |
| start-date |
默认开始日期(范围模式) |
string |
- |
| end-date |
默认结束日期(范围模式) |
string |
- |
| default-select-today |
默认选中今天 |
boolean |
true |
| min-date |
最小可选日期 |
string |
1950-01-01 |
| max-date |
最大可选日期 |
string |
今天 |
| min-year |
最小可选年份 |
number/string |
1950 |
| max-year |
最大可选年份 |
number/string |
2050 |
| change-year |
是否显示年份切换按钮 |
boolean |
true |
| change-month |
是否显示月份切换按钮 |
boolean |
true |
| active-bg-color |
选中日期背景色 |
string |
主题色 |
| active-color |
选中日期文字颜色 |
string |
白色 |
| range-bg-color |
范围内日期背景色 |
string |
主题色浅 |
| range-color |
范围内日期文字颜色 |
string |
主题色 |
| start-text |
开始日期提示文字 |
string |
开始 |
| end-text |
结束日期提示文字 |
string |
结束 |
| tool-tip |
顶部提示文字 |
string |
选择日期 |
| closeable |
是否显示关闭图标 |
boolean |
true |
| mask-close-able |
点击遮罩是否关闭 |
boolean |
true |
| safe-area-inset-bottom |
底部安全区适配 |
boolean |
false |
| border-radius |
弹窗圆角 |
number/string |
20 |
| z-index |
弹窗层级 |
number/string |
10075 |
| is-active-current |
选中日期是否高亮 |
boolean |
true |
| checkin-mode |
是否启用打卡模式 |
boolean |
false |
| checked-dates |
已打卡日期列表 |
array |
[] |
| today-checked |
今日是否已打卡 |
boolean |
false |
| checked-bg-color |
已打卡背景色 |
string |
橙色 |
| today-checked-bg-color |
今日已打卡背景色 |
string |
绿色 |
| unchecked-bg-color |
未打卡背景色 |
string |
灰色 |
| holidays |
节假日列表 |
array |
[] |
| workdays |
加班日列表 |
array |
[] |
| holiday-color |
节假日文字颜色 |
string |
红色 |
| workday-color |
加班日文字颜色 |
string |
蓝色 |
| show-festival |
是否显示内置节日 |
boolean |
false |
| festivals |
自定义节日配置 |
object |
{} |
| festival-color |
节日文字颜色 |
string |
主题色 |
| use-date-slot |
是否启用日期插槽 |
boolean |
false |
Events 事件
| 事件名 |
说明 |
回调参数 |
| change |
日期选择完成时触发 |
CalendarChangeDate / CalendarChangeRange |
Slots 插槽
| 名称 |
说明 |
| tooltip |
自定义顶部提示内容 |
| date |
自定义日期内容(作用域插槽) |
更多功能及用法参考 uView Pro 日历文档:uviewpro.cn/zh/componen…
八、总结
uView Pro 的 Calendar 日历组件是一个功能全面、设计精良的日期选择解决方案。从基础的单日期选择到复杂的打卡签到、价格日历,这些都能轻松应对。
使用建议:
-
选择合适的展示模式:弹窗模式适合临时选择,页面模式适合常驻展示
-
合理利用默认选中:通过
default-date 或 default-select-today 提升用户体验
-
注意日期格式:所有日期参数统一使用
YYYY-MM-DD 格式
-
自定义插槽优先级:使用
date 插槽时会覆盖农历、节日等默认显示
-
打卡模式注意:
today-checked 优先级高于 checkedDates 的自动判断
功能使用建议:
- 如需农历功能,请确保使用支持该功能的版本
- 如需打卡签到、节假日、自定义插槽等高级功能,请使用最新版本
如果你正在开发 uni-app 项目,需要一个功能强大、易于定制的日历组件,uView Pro 的 Calendar 值得一试,快来体验一下。
九、资源
本文基于 uView Pro v0.5.17 版本编写,部分功能可能需要更新版本支持。