
前端UI组件【免费下载链接】v-calendarAn elegant calendar and datepicker plugin for Vue.项目地址https://gitcode.com/gh_mirrors/vc/v-calendar点击查看免费下载本篇指南以 v-calendar 2.0 的 Calendar 组件公开 APIdocs/api/v2.0/calendar.md为核心骨架系统讲解其全部 Props、Events、Methods 与 Scoped Slots并结合 src/components/Calendar.vue 源码与 tests/unit/specs/Calendar.spec.js 测试用例深入揭示每个配置项背后的实现原理与调用链。读完本文你将能够按多行多列布局搭建日历、通过from-page/to-page控制起始与结束页面、用move/focusDate/showPageRange完成程序化导航、借助 scoped slots 完全自定义头部、日期单元格与 popover 内容并正确监听页切换、日期点击与周号点击等事件。概览Calendar 组件的定位Calendar 是 v-calendar 的核心组件负责渲染网格化的月份面板pane、导航箭头、周号、日期单元格以及附着在日期上的属性attribute与 popover。它的 API 由四大部分组成Props配置布局、页面、禁用范围、主题与本地化、Events页切换、日期交互与过渡生命周期、Methods程序化导航与Scoped Slots深度自定义渲染。从源码结构看src/components/Calendar.vue 的渲染函数会将每一页page委托给CalendarPane子组件渲染而 src/components/CalendarPane.vue 又逐日渲染CalendarDay最终由 src/components/index.js 统一对外注册导出。Props完整配置参考布局rows、columns、step、is-expandedProp类型默认值说明rowsNumber1显示的日历行数columnsNumber1显示的日历列数stepNumber0未设置时解析为rows * columns前后导航时一次跨过的月份数is-expandedBooleanfalse是否让日历横向铺满容器宽度rows与columns共同决定同一时刻展示的月份面板数量。源码中 Calendar.vue 的count计算属性 为this.rows * this.columnsstep_在未显式传入step时解析为countcount() { return this.rows * this.columns; }, step_() { return this.step || this.count; },因此默认单面板下点击一次箭头移动 1 个月若设置rows2、columns2共 4 面板默认step为 4即一次翻页同时切换 4 个月。面板本身由 CSS Grid 排列见 Calendar.vue 中gridTemplateColumns的动态计算style: { gridTemplateColumns: repeat(${this.columns}, 1fr), },当is-expanded为true时容器会添加vc-is-expanded类见 Calendar.vue 渲染逻辑配合 src/styles/base.css 中的样式使日历铺满可用宽度。标题与导航面板title-position、nav-visibilitytitle-positionString默认center取值left/center/right控制每个面板头部标题的对齐方式。源码中通过propOrDefault(titlePosition, titlePosition)解析最终作用于CalendarPane的vc-header align-${titlePosition}类见 CalendarPane.vue。nav-visibilityString默认undefined由 defaults.md 解析为focus控制导航面板点击标题弹出的月份/年份选择器的可见性取值focus、hover、visible、hidden。focus表示标题获得焦点或点击时才显示导航面板。页面过渡transitiontransitionString默认undefined面板切换动画类型取值slide-h水平滑动、slide-v垂直滑动、fade、none。默认值由 defaults 解析单面板rows 1 columns 1为slide-h多面板为fade见 defaults.md。源码中getPageTransition决定实际动画类名向后翻页使用slide-right/slide-down向前翻页使用slide-left/slide-up动画由CustomTransition包裹执行见 Calendar.vuegetPageTransition(oldPage, newPage, transition this.transition) { if (transition none) return transition; if ( transition fade || (!transition this.count 1) || !pageIsValid(oldPage) || !pageIsValid(newPage) ) { return fade; } const movePrev pageIsBeforePage(newPage, oldPage); if (transition slide-v) { return movePrev ? slide-down : slide-up; } return movePrev ? slide-right : slide-left; },页面控制from-page、from-date、to-page、to-datefrom-pageObject默认undefined解析为当前月位于第 0 行第 0 列的第一个面板所显示的页面{ month, year }。支持.sync修饰符双向绑定页切换时组件会发出update:from-page事件。源码中watch监听fromPage变化并触发refreshPages()见 Calendar.vue。from-dateDate用于计算from-page的日期。注意.sync修饰符对此 prop 无效因为它是单向输入真正对外同步的是update:from-page事件。to-pageObject默认undefined最后一个面板最大行/列处的页面。默认解析为rows * columns个月之后。同样支持.sync双向绑定。to-dateDate用于计算to-page的日期同样不支持.sync。文档明确警告不要同时给from-page和to-page赋值否则会导致导航行为错乱两者任选其一即可见 calendar.md。从源码看页面解析遵循明确的优先级链条。getDefaultInitialPage依次尝试①fromPageprop 或其计算值 → ②toPageprop 并向前偏移count - 1个月 → ③ 第一个带日期的 attribute → ④ 当月getDefaultInitialPage() { let page this.fromPage || this.pageForDate(this.fromDate); if (!pageIsValid(page)) { const toPage this.toPage || this.pageForDate(this.toPage); if (pageIsValid(toPage)) { page addPages(toPage, 1 - this.count); } } if (!pageIsValid(page)) { page this.getPageForAttributes(); } if (!pageIsValid(page)) { page this.pageForThisMonth(); } return page; },导航边界min-page、min-date、max-page、max-datemin-pageObject用户可导航到的最早页面{ month, year }。min-dateDate用于计算min-page的日期。max-pageObject用户可导航到的最晚页面。max-dateDate用于计算max-page的日期。源码中minPage_/maxPage_优先取显式的 page 对象否则由对应日期换算minPage_() { return this.minPage || this.pageForDate(this.minDate); }, maxPage_() { return this.maxPage || this.pageForDate(this.maxDate); },边界同时约束canMovePrev/canMoveNextCalendar.vue以及canMove方法从而禁用对应的导航箭头。在测试 tests/unit/specs/Calendar.spec.js 中正是通过断言.vc-arrow.is-left.is-disabled/.vc-arrow.is-right.is-disabled来验证边界生效。日期内容attributes、disabled-dates、available-datesattributesArray[Object]默认[]要在日历上显示的属性列表高亮、圆点、条、popover 等详见 attribute.md。源码中属性会进入AttributeStore统一管理见 Calendar.vueinitStore与 src/utils/attributeStore.js并随pages变化刷新到每个日期的attributesMap。disabled-datesDate | Range | Pattern禁止用户选择或导航到的日期可以是单个 JS Date、带start/end/span的范围对象或 日期模式 token如weekends、{ weekdays: [1, 7] }。available-dates同上仅这些日期可用其余全部禁用白名单语义。源码中二者被合并为一个disabledAttribute见 src/utils/mixins/root.jsdisabledDates_作为主集合availableDates_作为excludeDates反向排除最后以order: 100的高优先级渲染为禁用样式。格式化与本地化masks、color、is-dark、first-day-of-week、locale、timezonemasksObject各区块标题、星期标签、输入框、day popover 等的日期格式化掩码未设置时由 defaults.md 的默认值解析默认掩码如下{ title: MMMM YYYY, // 面板标题如 October 2026 weekdays: W, // 星期标签 navMonths: MMM, // 导航面板月份简称 input: [L, YYYY-MM-DD, YYYY/MM/DD], // 输入框解析格式 dayPopover: WWW, MMM D, YYYY, // 日期 popover 标题 data: [L, YYYY-MM-DD, YYYY/MM/DD], // 数据解析格式 }colorString默认blue主题强调色与 attribute 默认配色。源码通过new Theme({ color, isDark })构建主题对象见 src/utils/mixins/root.js并输出vc-${color}容器类。is-darkBoolean默认false深色模式开关对应 colors-dark-mode.md。first-day-of-weekNumber默认由 locale 决定每周第一天1: 周日 - 7: 周六。想交给 locale 自动决定就不要设置。localeString | Objectlocale 标识或完整的 locale 配置对象。未完全指定时由 defaults.md 或自动检测的浏览器语言解析。timezoneString显示日历所用的时区标识如UTC、America/New_York相关实现见 src/utils/locale.js 与 tests/timezones.js。周号显示show-weeknumbers、show-iso-weeknumbersshow-weeknumbersBoolean | String为true时在左侧显示周号也可传字符串指定位置left、left-outside、right、right-outside。show-iso-weeknumbersBoolean | String同上的 ISO 8601 周号isoWeeknumber。从 CalendarPane.vue 的实现可见周号单元格会在每周行首左或行尾右插入并随点击触发weeknumberclick事件const showWeeknumbersLeft this.showWeeknumbers_.startsWith(left); const showWeeknumbersRight this.showWeeknumbers_.startsWith(right);触摸交互disable-page-swipedisable-page-swipeBoolean禁用左右滑动切换页面的手势。默认启用手势Calendar.vuemounted中通过addHorizontalSwipeHandler注册滑动监听左滑moveNext()、右滑movePrev()此 prop 为true时不注册mounted() { if (!this.disablePageSwipe) { this.removeHandlers addHorizontalSwipeHandler( this.$refs.container, ({ toLeft, toRight }) { if (toLeft) this.moveNext(); else if (toRight) this.movePrev(); }, this.$defaults.touch, ); } },滑动灵敏度参数来自全局 defaults 的touch配置maxSwipeTime、minHorizontalSwipeDistance、maxVerticalSwipeDistance见 defaults.md。Events事件全览事件参数触发时机update:from-pagepage左/单面板切换到不同页面update:to-pagepage右面板切换到不同页面weeknumberclick{ weeknumber, days, event }点击周号内容元素dayclickday点击日期内容元素daymouseenterday鼠标进入日期内容元素daymouseleaveday鼠标离开日期内容元素dayfocusinday日期内容元素获得焦点dayfocusoutday日期内容元素失去焦点transition-start—切换到新页面的过渡开始transition-end—切换到新页面的过渡结束update:from-page与update:to-page是配合from-page/to-page使用.sync的关键事件。源码在 refreshPages 中每次翻页后统一发出this.$emit(update:from-page, fromPage); this.$emit(update:to-page, toPage);transition-start/transition-end由 Calendar.vue 的inTransition监听器 驱动CustomTransition的beforeEnter/afterEnter切换inTransition状态从而触发这两个事件transition-end同时也是move()返回 Promise 的 resolve 时机。weeknumberclick的参数结构完整定义如下实现见 CalendarPane.vue{ weeknumber: Number, // 被点击的周号 days: [Day], // 该周号对应的日期对象列表 event: MouseEvent, // 原生事件 }dayclick等日期事件由CalendarDay转发最终携带完整的 Day Object含date、inMonth、attributes、event等字段发出。Methods程序化导航调用组件方法前需要先给组件绑定 ref并在mounted生命周期之后调用v-calendar refcalendar /mounted() { const calendar this.$refs.calendar; calendar.showPageRange(new Date()); }move(Number | String | Date | Object)签名async move(arg, opts) Promise异步导航按月份数移动、移动到指定月份或指定日期。返回一个 Promise过渡完成时 resolve目标月份被禁用时 reject。参数参数类型说明argNumber / Date / String / Page Object目标月份依据opts.positionNumber多行多列布局下的目标面板位置负数表示从末尾倒数opts.transitionString覆盖transitionprop 的过渡类型slide-h、slide-v、fade、noneopts.forceBoolean即使目标月份被禁用也强制导航按月份数移动正数向前、负数向后每次移动的月数由step决定// 向前 5 个月等待过渡完成 await calendar.move(5); // 向后 5 个月等待过渡完成 await calendar.move(-5);移动到指定月份传入{ month, year }对象// 移动到 1983 年 1 月 await calendar.move({ month: 1, year: 1983 });移动到指定日期传入 Date 对象或可解析的日期字符串// 移动到今天所在的月份 await calendar.move(new Date()); // 移动到我的生日所在的月份 await calendar.move(1983-01-21);:::warningmove(date)只导航到日期所在月份过渡完成后不会聚焦该日期。若要同时聚焦请使用focusDate(date)。 :::源码中move的实现Calendar.vue会先经canMove校验目标页与minPage_/maxPage_边界比对见 canMove未设置force且越界时直接 rejectmove(arg, opts {}) { const canMove this.canMove(arg, opts); if (!opts.force !canMove) { return Promise.reject( new Error(Move target is disabled: ${JSON.stringify(opts)}), ); } ... }对应的测试用例覆盖了三种基本导航模式见 tests/unit/specs/Calendar.spec.jsit(:move should move to a date, async () { await wrapper.vm.move(new Date(2000, 0, 1), { transition: none }); expect(wrapper.find(.id-2000-01-01).exists()).toBe(true); }); it(:move should move forward by n months, async () { await wrapper.setProps({ fromPage: { month: 1, year: 2000 } }); await wrapper.vm.move(5, { transition: none }); expect(wrapper.find(.id-2000-06-01).exists()).toBe(true); });focusDate(String | Date)签名async focusDate(date, opts) Promise导航到指定日期所在月份并在过渡完成后聚焦该日期单元格。参数opts.position、opts.transition与move一致。源码实现Calendar.vue在move()完成后定位目标日期的.vc-focusable元素并调用原生focus()focusDate(date, opts {}) { return this.move(date, opts).then(() { const focusableEl this.$el.querySelector( .id-${this.$locale.getDayId(date)}.in-month .vc-focusable, ); if (focusableEl) { focusableEl.focus(); return Promise.resolve(true); } return Promise.resolve(false); }); },showPageRange(Date | Object)签名showPageRange(range, opts)导航到最合适展示给定日期范围的页面组合。支持四种入参形态const date new Date(2020, 0, 1); // 2020 年 1 月 const page { month: 2, year: 2020 }; // 2020 年 2 月 // 传入日期 calendar.showPageRange(date); // 传入页面对象 calendar.showPageRange(page); // 从某日期/页面开始 calendar.showPageRange({ from: date }); // 到某日期/页面结束 calendar.showPageRange({ to: page }); // 从某日期/页面开始到某日期/页面结束 calendar.showPageRange({ from: date, to: page });源码实现Calendar.vue会将日期统一换算为页面若目标toPage超出当前末页则向前偏移pages.length - 1个月但不会早于fromPage从而保证整个范围尽可能落在可视面板内。Scoped Slots深度自定义渲染header 与 header-titleheader整个日历头部每个面板一个props 为 Page Object含monthLabel、yearLabel、movePrevMonth()、moveNextMonth()等。源码在 CalendarPane.vue 中先尝试该插槽未提供时渲染默认头部。header-title头部标题props 同样为 Page Object。设置title-transition时该插槽内容会参与动画。day-content完全自定义日期单元格PropsProp类型说明dayDay Object日期对象dayEventsObject需要映射到自定义内容 DOM 元素上的事件如click、mouseenter等attributesArray该日期上按顺序排列的属性列表attributesMapObject以属性 key 为键的属性映射通过该插槽可以替换默认日期内容例如在日期格内显示农历、角标或自定义样式v-calendar template #day-content{ day, dayEvents, attributes } div classcustom-day v-binddayEvents :class{ is-today: day.isToday } span{{ day.day }}/span span v-ifattributes.length classvc-dot / /div /template /v-calendarday-popover自定义属性 popover 内容PropsProp类型说明dayDay Object日期对象attributesArray该日期上带 popover 的有序属性列表masksObject解析后的 locale 掩码formatFunction用自定义日期和掩码格式化日期dayTitleString使用dayPopover掩码预格式化好的标题字符串updateLayoutFunction内容变化时强制刷新 popover 布局hideFunction强制隐藏 popover默认 popover 渲染逻辑见 Calendar.vue 的getDayPopover先用masks.dayPopover格式化dayTitle作为头部再逐条渲染带 popover 的属性行。插槽注入的这些工具函数让你能在自定义内容如远程加载的数据变化后手动updateLayout()或hide()。导航按钮插槽header-left-button/header-right-button日历头部左右两侧的翻页按钮。源码中Calendar.vue默认渲染SvgIcon箭头点击时调用move(-step_ / step_)可通过插槽自定义图标或文案。nav-left-button/nav-right-button导航面板月份/年份选择器头部的左右按钮。实战示例综合配置一个多面板日历综合以上 API一个支持双面板、双向同步起始页、限制导航范围并自定义日期的完整示例template v-calendar :rows1 :columns2 :from-page.syncfromPage :min-datenew Date(2024, 0, 1) :max-datenew Date(2026, 11, 31) :attributesattributes :disabled-dates{ weekdays: [1, 7] } transitionfade is-expanded show-iso-weeknumbersright dayclickonDayClick transition-startonTransitionStart transition-endonTransitionEnd template #day-content{ day, dayEvents } div v-binddayEvents classmy-day-content{{ day.day }}/div /template /v-calendar /template script export default { data() { return { fromPage: { month: 1, year: 2025 }, attributes: [ { key: today, highlight: true, dates: new Date(), dot: { color: red }, }, ], }; }, methods: { onDayClick(day) { console.log(clicked, day.date); }, onTransitionStart() {}, onTransitionEnd() { // 此处可安全执行依赖新页面已渲染的逻辑 }, }, }; /script关联文档速览Defaults全局默认值navVisibility、transition、masks、screens、locale等的全局解析规则Page Object事件与插槽中携带的页面对象字段Day Object日期事件与day-content插槽中的日期对象字段Attributeattributesprop 支持的高亮、圆点、条、popover 与内容配置Date Patternsdisabled-dates/available-dates支持的模式 token 语法Date Picker基于 Calendar 封装的下拉/内联日期选择器 API结语Calendar 组件的 API 设计遵循“配置驱动 插槽开放”的原则布局、页面、边界、格式全部由 props 声明式控制翻页与聚焦由三个异步方法统一处理事件链覆盖从日期交互到过渡生命周期的完整环节scoped slots 则在需要时允许你将默认渲染完全替换。本文所引用的源码路径与测试用例均可直接在仓库中查阅作为进一步深入理解组件内部行为的起点。赞分享前端UI组件【免费下载链接】v-calendarAn elegant calendar and datepicker plugin for Vue.项目地址https://gitcode.com/gh_mirrors/vc/v-calendar点击查看免费下载相关推荐v-calendar 组件 API 完全指南属性、事件、方法与会话插槽v1.0v calendar 组件 API 完全指南属性、事件、方法与会话插槽v1.0 本指南围绕 v calendar 的 Calendar 组件 API 展开前端UI组件v-calendar 2.0 日期选择器完整指南v-date-picker 的 Props、事件、方法与时槽深度解析v calendar 2.0 日期选择器完整指南v date picker 的 Props、事件、方法与时槽深度解析 v calendar 是 Vue 生态中前端UI组件v-calendar 日期选择器v-date-pickerAPI 完全指南Props、事件、插槽与源码级实现解析v calendar 日期选择器v date pickerAPI 完全指南Props、事件、插槽与源码级实现解析 本文以 v calendar 1.x 时前端UI组件上一篇农业计算机视觉终极指南如何实现精准作物监测与产量预测下一篇如何高效管理Asciidoctor文档包含模块化文档编写终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考