乐于分享
好东西不私藏

uni-app全能日历组件,支持农历、酒店预订、打卡签到、价格日历多种场景

uni-app全能日历组件,支持农历、酒店预订、打卡签到、价格日历多种场景

一、uView Pro 的 Calendar 日历组件

在 uni-app 开发中,日期选择是一个高频需求场景。无论是酒店预订的入住离店时间选择、电商平台的商品预约、还是日常应用的打卡签到,一个功能完善、体验优秀的日历组件都是必不可少的。

uView Pro 作为 uni-app 生态中备受关注的 Vue3 组件库,其 Calendar 日历组件 经过了多个版本的迭代优化,从最初的基础日期选择,逐步演进为支持农历显示、打卡签到、节假日标记、自定义价格日历等丰富功能的综合型组件。

本文将深入解析 uView Pro Calendar 组件的核心特性、实现原理以及实际应用场景,帮助你快速掌握这个强大的日期选择利器。

二、组件概览:功能特性总览

uView Pro 的 Calendar 日历组件具有以下核心特性:

基础功能

  • ✅ 支持单日期选择和日期范围选择两种模式
  • ✅ 底部弹窗和页面嵌入两种展示方式
  • ✅ 年月切换导航,支持自定义年份范围
  • ✅ 日期范围限制,防止选择无效日期

进阶功能

  • ✅ 农历显示支持,自动计算农历日期
  • ✅ 打卡签到模式,支持已打卡/未打卡状态展示
  • ✅ 节假日和加班日标记,显示”休”/”班”标识
  • ✅ 内置中国传统节日,支持自定义节日配置
  • ✅ 自定义日期内容插槽,适用于价格日历等场景

交互优化

  • ✅ 默认选中今天,支持指定默认日期
  • ✅ 只读模式,禁止日期选择
  • ✅ 选中效果可配置,适应不同视觉需求

三、基础使用:快速上手

3.1 单日期选择模式

单日期选择是最常用的场景,比如选择生日、预约日期等。

<template><view><u-calendarv-model="show"mode="date" @change="onChange"></u-calendar><u-button @click="show = true">选择日期</u-button></view></template><scriptsetuplang="ts">import { ref } from'vue'import type { CalendarChangeDate } from'uview-pro/types/global'const show = ref(false)functiononChange(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-calendarv-model="show"mode="range"start-text="入住"end-text="离店"        @change="onRangeChange"    ><template #tooltip><viewclass="tip">请选择入住和离店时间</view></template></u-calendar></template><scriptsetuplang="ts">import { ref } from'vue'import type { CalendarChangeRange } from'uview-pro/types/global'const show = ref(false)functiononRangeChange(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-calendarv-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><viewclass="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><scriptsetup>import { ref } from'vue'// 已打卡日期列表const checkedDates = ref(['2024-01-01''2024-01-02''2024-01-03','2024-01-05'])// 今日打卡状态(优先级高于自动判断)const todayChecked = ref(true)</script>

打卡模式的显示规则:

  1. 今日已打卡:绿色圆形背景,显示白色对勾
  2. 其他已打卡日期:橙色圆形背景,显示日期
  3. 未打卡日期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><scriptsetup>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><scriptsetup>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>

优先级规则:

  1. 特定年份格式(YYYY-MM-DD)优先级最高
  2. 每年固定格式(MM-DD)次之
  3. 内置节日优先级最低

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><scriptsetup>import { ref } from'vue'// 价格数据const priceMap = ref({'2024-01-01'299,'2024-01-02'399,'2024-01-03'359,// ...})functiongetPriceText(date{if (date.isToday) return'今天'const price = priceMap.value[date.date]return price ? ${price}` : ''}functiongetPriceClass(date{if (date.isSelected) return'price-selected'if (date.isToday) return'price-today'return'price-normal'}</script><stylescoped>.price-today {color#19be6b;font-weight: bold;}.price-normal {color#909399;font-size22rpx;}.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 组件的日历渲染基于以下核心算法:

// 获取某月天数functiongetMonthDay(year: number, month: number{returnnewDate(year, month, 0).getDate()}// 获取某月第一天星期几(0-6)functiongetWeekday(year: number, month: number{let date = newDate(`${year}/${month}/01 00:00:00`)return date.getDay()}

渲染流程:

  1. 计算当月第一天是星期几,生成前置空白格子
  2. 计算当月总天数,生成日期格子
  3. 根据选中状态计算每个格子的样式
  4. 如果有农历,调用农历转换库计算农历日期

5.2 农历计算

组件使用了独立的农历计算工具 Calendar.solar2lunar,将公历日期转换为农历:

functiongetLunar(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 范围选择逻辑

范围选择采用两次点击确定起止时间的交互方式:

functiondateClick(dayIdx: number{const d = dayIdx + 1const date = `${year.value}-${month.value}-${d}`if (props.mode == 'range') {// 判断是设置开始日期还是结束日期const compare = newDate(date).getTime() < newDate(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-calendarv-model="show"mode="range"start-text="入住"end-text="离店":min-date="minDate":max-date="maxDate"    @change="onDateChange"><template #tooltip><viewclass="hotel-tip"><text>请选择入住和离店日期</text><textclass="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 }"><viewclass="flight-price"><textclass="day">{{ date.day }}</text><textclass="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 官方文档 https://uviewpro.cn

八、总结与建议

uView Pro 的 Calendar 日历组件是一个功能全面、设计精良的日期选择解决方案。从基础的单日期选择到复杂的打卡签到、价格日历,这些都能轻松应对。

使用建议:

  1. 选择合适的展示模式:弹窗模式适合临时选择,页面模式适合常驻展示
  2. 合理利用默认选中:通过 default-date 或 default-select-today 提升用户体验
  3. 注意日期格式:所有日期参数统一使用 YYYY-MM-DD 格式
  4. 自定义插槽优先级:使用 date 插槽时会覆盖农历、节日等默认显示
  5. 打卡模式注意today-checked 优先级高于 checkedDates 的自动判断

功能使用注意:

  • 如需农历功能,请确保使用支持该功能的版本
  • 如需打卡签到、节假日、自定义插槽等高级功能,请使用 uView Pro 最新版本

如果你正在开发 uni-app 项目,需要一个功能强大、易于定制的日历组件,uView Pro 的 Calendar 值得一试,快来体验一下。

九、资源

  • 📚 uView Pro 官方文档:https://uviewpro.cn
  • 📦 开源地址:https://github.com/anyup/uView-Pro
  • 💬 技术交流:如有问题欢迎留言讨论

注意:本文基于 uView Pro v0.5.17 版本编写,部分功能可能需要更新版本支持。

以上功能,可以直接进入uView Pro 小程序体验:

uView Pro 开源组件使用交流:

求关注!