Skip to content

Calendar 日历 - Vant 4

Calendar 日历

📅 介绍

想象一下,你正在规划一次浪漫的旅行,或者安排一个重要的商务会议 🗓️。这时候,一个好用的日历组件就像是你的贴心助手!

Calendar 日历组件就是这样一个神奇的工具 ✨。它不仅颜值超高,功能还特别强大:

  • 🎯 单日选择:轻点一下,锁定那个特殊的日子
  • 🎨 多日选择:想选几天就选几天,自由度满分
  • 📅 区间选择:开始和结束,一气呵成
  • 🌈 自定义样式:想要什么颜色,随你心意

无论是预订酒店、安排会议还是设置生日提醒,Calendar 都能给你最直观、最便捷的日期选择体验!就像有了一个会读心术的日历管家 🎭。

📦 引入

通过以下方式来全局注册组件,更多注册方式请参考组件注册

js
import { createApp } from'vue'; 
import { Calendar } from'vant'; 
const app = createApp(); 
app.use(Calendar);

🎯 代码演示

选择切换模式

想象一下翻阅一本厚厚的日历本 📖,一页页翻找目标日期是不是很累?默认情况下,Calendar 会把所有月份像摊煎饼一样平铺展示,虽然一目了然,但月份太多时就像在信息海洋里游泳 🏊‍♀️。

这时候 switch-mode 属性就像给日历装上了"传送门" ⚡!设置后会出现年月切换按钮,让用户像坐火箭一样快速跳转到目标月份。再也不用在茫茫日期海中慢慢寻找啦!

html

选择单个日期

就像在日历上用红笔圈出重要日子一样简单 🔴!这个例子展示了如何把 Calendar 和 Cell 单元格完美搭配使用。

用户轻轻一点,日期就被"捕获"了,然后 confirm 事件会像信使一样把好消息传递给你 📮。整个过程行云流水,就像点餐一样简单!

html
js
import { ref } from'vue'; 
export default { setup() { 
    const date = ref(''); 
    const show = ref(false); 
    const formatDate = (date) => { 
        return`${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`; 
    }; 
    const onConfirm = (value) => { 
        show.value = false; 
        date.value = formatDate(value); 
    }; 
    return { date, show, onConfirm, }; 
    }
};

选择多个日期

有时候一个日期怎么够用?比如你要安排一周的健身计划,或者标记所有的节假日 🎉!

type 设置为 multiple,Calendar 就变身成了"贪心的收集家" 🗂️,可以一口气选择多个日期。这时候 confirm 事件会贴心地把所有选中的日期打包成一个数组送给你,就像收集邮票一样有序!

html
js
import { ref } from'vue'; 
export default { 
    setup() { 
        const text = ref(''); 
        const show = ref(false); 
        const onConfirm = (dates) => { show.value = false; text.value = `选择了 ${dates.length} 个日期`; }; 
        return { text, show, onConfirm, }; 
    }, 
};

选择日期区间

计划一次完美的假期?安排一个项目周期?这时候你需要的不是零散的日期,而是一个完整的时间段 🌅🌇!

type 设置为 range,Calendar 就像一个专业的时间管家,帮你圈定一个完整的日期区间。选择完成后,它会很贴心地把开始日期和结束日期分别放在数组的第一位和第二位,就像给你一张标注了起点和终点的地图 🗺️!

html
js
import { ref } from'vue'; 
export default { 
    setup() { 
        const date = ref(''); 
        const show = ref(false); 
        const formatDate = (date) => `${date.getMonth() + 1}/${date.getDate()}`; 
        const onConfirm = (values) => { const [start, end] = values; show.value = false; date.value = `${formatDate(start)} - ${formatDate(end)}`; }; 
        return { date, show, onConfirm, }; 
    }, 
};

Tips: 默认情况下,日期区间的起止时间不能为同一天,可以通过设置 allow-same-day 属性来允许选择同一天。

快捷选择

有时候,确认按钮就像是多余的"门槛" 🚪。想要更加流畅的体验?

show-confirm 设置为 false,确认按钮就会悄悄隐身!这样用户一选择日期,confirm 事件就会立刻响应,就像闪电一样快 ⚡。特别适合那些追求极简体验的场景!

html

自定义颜色

谁说日历只能是蓝色的?你的品牌色是什么,日历就可以是什么颜色 🎨!

通过 color 属性,你可以让日历穿上任何你喜欢的"外衣"。无论是选中的日期还是底部的按钮,都会乖乖地换上新装。就像给日历做了一次时尚改造 💄!

html

自定义日期范围

有些日期是"禁区" 🚫,有些日期才是"黄金时段" ✨!

通过 min-datemax-date 这对"守门员",你可以精确控制用户能选择的日期范围。就像给日历画了一个圈,圈外的日期都变成了"看得见摸不着"的存在。特别适合预订系统、活动报名等有时间限制的场景!

html
js
import { ref } from'vue'; 
export default { setup() { const show = ref(false); 
return { show, minDate: newDate(2010, 0, 1), maxDate: newDate(2010, 0, 31), }; }, };

自定义按钮文字

"确认"这个词太普通了?想要更有个性的按钮文案 💬?

confirm-text 可以给按钮换个更酷的说法,比如"就是它了!"、"选定"、"Go!"等等。而 confirm-disabled-text 则负责在按钮不可用时给用户一个贴心的提示。就像给按钮配了专属的"台词" 🎭!

html

自定义日期文案

想让你的日历更有"人情味"?比如在特殊日子显示"生日快乐"、"发工资"、"周末愉快" 🎂?

formatter 函数就像是日历的"化妆师" 💄,它可以给每一个日期格子添加个性化的内容。无论是顶部提示、底部说明,还是改变日期文字本身,都能轻松搞定。让你的日历从此告别单调,变得生动有趣!

html
js
exportdefault { setup() { constformatter = (day) => { const month = day.date.getMonth() + 1; const date = day.date.getDate(); if (month === 5) { if (date === 1) { day.topInfo = '劳动节'; } elseif (date === 4) { day.topInfo = '青年节'; } elseif (date === 11) { day.text = '今天'; } } if (day.type === 'start') { day.bottomInfo = '入住'; } elseif (day.type === 'end') { day.bottomInfo = '离店'; } return day; }; return { formatter, }; }, };

自定义弹出位置

通过 position 属性自定义弹出层的弹出位置,可选值为 topleftright

html

日期区间最大范围

选择日期区间时,可以通过 max-range 属性来指定最多可选天数,选择的范围超过最多可选天数时,会弹出相应的提示文案。

html

自定义周起始日

通过 first-day-of-week 属性设置一周从哪天开始。

html

平铺展示

poppable 设置为 false,日历会直接展示在页面内,而不是以弹层的形式出现。

html

API

Props

参数说明类型默认值
type选择类型:single 表示选择单个日期,multiple 表示选择多个日期,range 表示选择日期区间stringsingle
switch-mode v4.9.0切换模式:none 平铺展示所有月份,不展示切换按钮,month 支持按月切换,展示上个月/下个月按钮,year-month 支持按年切换,也支持按月切换,展示上一年/下一年,上个月/下个月按钮stringnone
title日历标题string日期选择
color主题色,对底部按钮和选中日期生效string#1989fa

| min-date | 可选择的最小日期 | Date | switch-modenone 时为当前日期 | | max-date | 可选择的最大日期 | Date | switch-modenone 时为当前日期的六个月后 | | default-date | 默认选中的日期,typemultiplerange 时为数组,传入 null 表示默认不选择 | Date | Date[] | null | 今天 | | row-height | 日期行高 | number | string | 64 | | formatter | 日期格式化函数 | (day: Day) => Day | - | | poppable | 是否以弹层的形式展示日历 | boolean | true | | lazy-render | 是否只渲染可视区域的内容 | boolean | true | | show-mark | 是否显示月份背景水印 | boolean | true | | show-title | 是否展示日历标题 | boolean | true | | show-subtitle | 是否展示日历副标题(年月) | boolean | true | | show-confirm | 是否展示确认按钮 | boolean | true | | readonly | 是否为只读状态,只读状态下不能选择日期 | boolean | false | | confirm-text | 确认按钮的文字 | string | 确认 | | confirm-disabled-text | 确认按钮处于禁用状态时的文字 | string | 确认 | | first-day-of-week | 设置周起始日 | 0-6 | 0 |

Calendar Poppable Props

当 Calendar 的 poppabletrue 时,支持以下 props:

参数说明类型默认值
v-model:show是否显示日历弹窗booleanfalse
position弹出位置,可选值为 top``right``leftstringbottom
round是否显示圆角弹窗booleantrue
close-on-popstate是否在页面回退时自动关闭booleantrue
close-on-click-overlay是否在点击遮罩层后关闭booleantrue
safe-area-inset-top是否开启顶部安全区适配booleanfalse

| safe-area-inset-bottom | 是否开启底部安全区适配 | boolean | true |

| teleport | 指定挂载的节点,等同于 Teleport 组件的 to 属性 | string | Element | - |

Calendar Range Props

当 Calendar 的 typerange 时,支持以下 props:

参数说明类型默认值
max-range日期区间最多可选天数*numberstring*
range-prompt范围选择超过最多可选天数时的提示文案string最多选择 xx 天
show-range-prompt范围选择超过最多可选天数时,是否展示提示文案booleantrue
allow-same-day是否允许日期范围的起止时间为同一天booleanfalse

Calendar Multiple Props

当 Calendar 的 typemultiple 时,支持以下 props:

参数说明类型默认值
max-range日期最多可选天数*numberstring*
range-prompt选择超过最多可选天数时的提示文案string最多选择 xx 天

Day 数据结构

日历中的每个日期都对应一个 Day 对象,通过formatter属性可以自定义 Day 对象的内容

键名说明类型
date日期对应的 Date 对象Date
type日期类型,可选值为 selectedstartmiddleenddisabledstart-endmultiple-selectedmultiple-middleplaceholderstring
text中间显示的文字string
topInfo上方的提示信息string
bottomInfo下方的提示信息string
className额外类名string

Events

事件名说明回调参数
select点击并选中任意日期时触发*value: Date
confirm日期选择完成后触发,若 show-confirmtrue,则点击确认按钮后触发*value: Date
open打开弹出层时触发-
close关闭弹出层时触发-
opened打开弹出层且动画结束后触发-
closed关闭弹出层且动画结束后触发-
unselect当日历组件的 typemultiple 时,取消选中日期时触发value: Date
month-show当某个月份进入可视区域时触发(switch-modenone 时生效){ date: Date, title: string }
over-range范围选择超过最多可选天数时触发-
click-subtitle点击日历副标题时触发event: MouseEvent
click-disabled-date v4.7.0点击禁用日期时触发*value: Date
click-overlay v4.9.16点击遮罩层时触发event: MouseEvent
panel-change日历面板切换时触发(switch-mode 不为 none 时生效){ date: Date }

Slots

名称说明参数
title自定义标题-
subtitle自定义日历副标题{ text: string, date?: Date }
month-title v4.0.9自定义每个月份的小标题{ text: string, date: Date }
footer自定义底部区域内容-
confirm-text自定义确认按钮的内容{ disabled: boolean }
top-info自定义日期上方的提示信息day: Day
bottom-info自定义日期下方的提示信息day: Day
text自定义日期内容day: Day
prev-month自定义上个月按钮{ disabled: boolean }
prev-year自定义上一年按钮{ disabled: boolean }
next-month自定义下个月按钮{ disabled: boolean }
next-year自定义下一年按钮{ disabled: boolean }

方法

通过 ref 可以获取到 Calendar 实例并调用实例方法,详见组件实例方法

方法名说明参数返回值
reset将选中的日期重置到指定日期,未传参时会重置到默认日期*date?: DateDate[]*
scrollToDate滚动到某个日期date: Date-
getSelectedDate获取选中的日期-*Date

类型定义

组件导出以下类型定义:

ts
import type { CalendarSwitchMode, CalendarType, CalendarProps, CalendarDayItem, CalendarDayType, CalendarInstance, } from'vant';

CalendarInstance 是组件实例的类型,用法如下:

ts
import { ref } from'vue'; 
import type { CalendarInstance } from'vant'; 
const calendarRef = ref<CalendarInstance>(); 
calendarRef.value?.reset();

主题定制

样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件

名称默认值描述
--van-calendar-backgroundvar(--van-background-2)-
--van-calendar-popup-height80%-
--van-calendar-header-shadow0 2px 10px rgba(125, 126, 128, 0.16)-
--van-calendar-header-title-height44px-
--van-calendar-header-title-font-sizevar(--van-font-size-lg)-
--van-calendar-header-subtitle-font-sizevar(--van-font-size-md)-
--van-calendar-header-action-width28px-
--van-calendar-header-action-colorvar(--van-text-color)-
--van-calendar-header-action-disabled-colorvar(--van-text-color-3)-
--van-calendar-weekdays-height30px-
--van-calendar-weekdays-font-sizevar(--van-font-size-sm)-
--van-calendar-month-title-font-sizevar(--van-font-size-md)-
--van-calendar-month-mark-colorfade(var(--van-gray-2), 80%)-
--van-calendar-month-mark-font-size160px-
--van-calendar-day-height64px-
--van-calendar-day-font-sizevar(--van-font-size-lg)-
--van-calendar-day-margin-bottom4px-
--van-calendar-day-disabled-colorvar(--van-text-color-3)-
--van-calendar-range-edge-colorvar(--van-white)-
--van-calendar-range-edge-backgroundvar(--van-primary-color)-
--van-calendar-range-middle-colorvar(--van-primary-color)-
--van-calendar-range-middle-background-opacity0.1-
--van-calendar-selected-day-size54px-
--van-calendar-selected-day-colorvar(--van-white)-
--van-calendar-selected-day-backgroundvar(--van-primary-color)-
--van-calendar-info-font-sizevar(--van-font-size-xs)-
--van-calendar-info-line-heightvar(--van-line-height-xs)-
--van-calendar-confirm-button-height36px-
--van-calendar-confirm-button-margin7px 0-

常见问题

如何在 formatter 中使用异步返回的数据?

如果需要在 formatter 中使用异步返回的数据,可以使用计算属性动态创建 formatter 函数,示例如下:

js
const asyncData = ref(); 
const formatter = computed(() => { if (!asyncData.value) { return(day) => day; } 
return(day) => { day.bottomInfo = asyncData.value; return day; }; }); 
setTimeout(() => { asyncData.value = '后端文案'; }, 3000);

在 iOS 系统上初始化组件失败?

如果你遇到了在 iOS 上无法渲染组件的问题,请确认在创建 Date 对象时没有使用new Date('2020-01-01')这样的写法,iOS 不支持以中划线分隔的日期格式,正确写法是new Date('2020/01/01')

对此问题的详细解释:stackoverflow

或者,你应该采用一种在各个系统和浏览器上兼容性更好的写法:new Date(2020, 0, 1),但是需要注意的是,月份是从 0 开始的。

🎯 最佳实践

💡 使用场景推荐

Calendar 组件就像一把万能钥匙,适用于各种需要日期选择的场景:

🏨 酒店预订系统

js
// 设置入住和离店日期,限制最少住宿天数
<van-calendar
  type="range"
  :min-date="new Date()"
  :max-range="30"
  :formatter="hotelFormatter"
/>

📅 会议室预订

js
// 只允许选择工作日,排除周末
<van-calendar
  type="multiple"
  :formatter="workdayFormatter"
  :min-date="new Date()"
/>

🎂 生日提醒设置

js
// 单日选择,可以选择过去的日期
<van-calendar
  type="single"
  :max-date="new Date()"
  title="选择生日"
/>

⚡ 性能优化小贴士

  1. 合理使用 lazy-render:对于月份较多的日历,开启懒渲染可以显著提升性能
  2. 避免频繁更新 formatter:formatter 函数应该保持稳定,避免在每次渲染时创建新函数
  3. 使用 switch-mode:当需要展示大量月份时,使用切换模式而不是平铺模式

🎨 设计建议

  • 颜色搭配:选择与品牌色调和谐的主题色,避免过于鲜艳的颜色
  • 文案友好:使用用户熟悉的语言,比如"选择日期"比"Date Selection"更亲切
  • 反馈及时:在用户操作后及时给予视觉反馈,提升交互体验

🔗 相关组件

📚 延伸阅读


💡 小提示:Calendar 组件不仅仅是一个日期选择工具,更是提升用户体验的重要组件。合理运用它的各种特性,可以让你的应用更加人性化和专业!

基于Vant构建的企业级移动端解决方案