Appearance
Calendar 日历
按照日历形式展示数据的容器。
代码演示
基础用法
一个通用的日历面板,支持年/月切换。
2025
Sep
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
31 | 01 | 02 | 03 | 04 | 05 | 06 |
07 | 08 | 09 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 01 | 02 | 03 | 04 |
05 | 06 | 07 | 08 | 09 | 10 | 11 |
vue
<template>
<a-calendar v-model:value="value" @panelChange="onPanelChange" />
</template>
<script setup>
import { ref } from 'vue';
const value = ref();
const onPanelChange = (value, mode) => {
console.log(value, mode);
};
</script>卡片模式
用于嵌套在空间有限的容器中。
2025
Sep
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
31 | 01 | 02 | 03 | 04 | 05 | 06 |
07 | 08 | 09 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 01 | 02 | 03 | 04 |
05 | 06 | 07 | 08 | 09 | 10 | 11 |
vue
<template>
<div :style="{ width: '300px', border: '1px solid #d9d9d9', borderRadius: '4px' }">
<a-calendar v-model:value="value" :fullscreen="false" @panelChange="onPanelChange" />
</div>
</template>
<script setup>
import { ref } from 'vue';
const value = ref();
const onPanelChange = (value, mode) => {
console.log(value, mode);
};
</script>通知事项日历
一个复杂的应用示例,用 dateCellRender 和 monthCellRender 函数来自定义需要渲染的数据。
2025
Sep
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
31 | 01 | 02 | 03 | 04 | 05 | 06 |
07 | 08
| 09 | 10
| 11 | 12 | 13 |
14 | 15
| 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 01 | 02 | 03 | 04 |
05 | 06 | 07 | 08
| 09 | 10
| 11 |
vue
<template>
<a-calendar v-model:value="value">
<template #dateCellRender="{ current }">
<ul class="events">
<li v-for="item in getListData(current)" :key="item.content">
<a-badge :status="item.type" :text="item.content" />
</li>
</ul>
</template>
<template #monthCellRender="{ current }">
<div v-if="getMonthData(current)" class="notes-month">
<section>{{ getMonthData(current) }}</section>
<span>Backlog number</span>
</div>
</template>
</a-calendar>
</template>
<script setup>
import { ref } from 'vue';
const value = ref();
const getListData = value => {
let listData;
switch (value.date()) {
case 8:
listData = [
{
type: 'warning',
content: 'This is warning event.',
},
{
type: 'success',
content: 'This is usual event.',
},
];
break;
case 10:
listData = [
{
type: 'warning',
content: 'This is warning event.',
},
{
type: 'success',
content: 'This is usual event.',
},
{
type: 'error',
content: 'This is error event.',
},
];
break;
case 15:
listData = [
{
type: 'warning',
content: 'This is warning event',
},
{
type: 'success',
content: 'This is very long usual event。。....',
},
{
type: 'error',
content: 'This is error event 1.',
},
{
type: 'error',
content: 'This is error event 2.',
},
{
type: 'error',
content: 'This is error event 3.',
},
{
type: 'error',
content: 'This is error event 4.',
},
];
break;
default:
}
return listData || [];
};
const getMonthData = value => {
if (value.month() === 8) {
return 1394;
}
};
</script>
<style scoped>
.events {
list-style: none;
margin: 0;
padding: 0;
}
.events .ant-badge-status {
overflow: hidden;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
font-size: 12px;
}
.notes-month {
text-align: center;
font-size: 28px;
}
.notes-month section {
font-size: 28px;
}
</style>选择功能
一个通用的日历面板,支持年/月切换。
2017
Jan
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
01 | 02 | 03 | 04 | 05 | 06 | 07 |
08 | 09 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 01 | 02 | 03 | 04 |
05 | 06 | 07 | 08 | 09 | 10 | 11 |
vue
<template>
<a-alert :message="`You selected date: ${selectedValue && selectedValue.format('YYYY-MM-DD')}`" />
<a-calendar :value="date" @select="onSelect" @panelChange="onPanelChange" />
</template>
<script setup>
import { ref } from 'vue';
import dayjs from 'dayjs';
const date = ref(dayjs('2017-01-25'));
const selectedValue = ref(dayjs('2017-01-25'));
const onSelect = value => {
date.value = value;
selectedValue.value = value;
};
const onPanelChange = value => {
date.value = value;
};
</script>自定义头部
自定义日历头部内容。
Custom header
2025
Sep
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
31 | 01 | 02 | 03 | 04 | 05 | 06 |
07 | 08 | 09 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 01 | 02 | 03 | 04 |
05 | 06 | 07 | 08 | 09 | 10 | 11 |
vue
<template>
<div style="width: 300px; border: 1px solid #d9d9d9; border-radius: 4px">
<a-calendar v-model:value="value" :fullscreen="false" @panelChange="onPanelChange">
<template #headerRender="{ value: current, type, onChange, onTypeChange }">
<div style="padding: 10px">
<div style="margin-bottom: 10px">Custom header</div>
<a-row type="flex" justify="space-between">
<a-col>
<a-radio-group size="small" :value="type" @change="e => onTypeChange(e.target.value)">
<a-radio-button value="month">Month</a-radio-button>
<a-radio-button value="year">Year</a-radio-button>
</a-radio-group>
</a-col>
<a-col>
<a-select
size="small"
:dropdown-match-select-width="false"
class="my-year-select"
:value="String(current.year())"
@change="
newYear => {
onChange(current.year(+newYear));
}
"
>
<a-select-option
v-for="val in getYears(current)"
:key="String(val)"
class="year-item"
>
{{ val }}
</a-select-option>
</a-select>
</a-col>
<a-col>
<a-select
size="small"
:dropdown-match-select-width="false"
:value="String(current.month())"
@change="
selectedMonth => {
onChange(current.month(parseInt(String(selectedMonth), 10)));
}
"
>
<a-select-option
v-for="(val, index) in getMonths(current)"
:key="String(index)"
class="month-item"
>
{{ val }}
</a-select-option>
</a-select>
</a-col>
</a-row>
</div>
</template>
</a-calendar>
</div>
</template>
<script setup>
import { ref } from 'vue';
const value = ref();
const onPanelChange = (value, mode) => {
console.log(value, mode);
};
const getMonths = value => {
const localeData = value.localeData();
const months = [];
for (let i = 0; i < 12; i++) {
months.push(localeData.monthsShort(value.month(i)));
}
return months;
};
const getYears = value => {
const year = value.year();
const years = [];
for (let i = year - 10; i < year + 10; i += 1) {
years.push(i);
}
return years;
};
</script>API
TIP
Calendar 部分 locale 是从 value 中读取,所以请先正确设置 dayjs 的 locale。
vue
// 默认语言为 en-US,所以如果需要使用其他语言,推荐在入口文件全局设置 locale
// import dayjs from 'dayjs';
// import 'dayjs/locale/zh-cn';
// dayjs.locale('zh-cn');
<a-calendar v-model:value="value" @panelChange="onPanelChange" @select="onSelect"></a-calendar>| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| dateCellRender | 作用域插槽,用来自定义渲染日期单元格,返回内容会被追加到单元格 | v-slot:dateCellRender="{current: dayjs}" | - |
| dateFullCellRender | 作用域插槽,自定义渲染日期单元格,返回内容覆盖单元格 | v-slot:dateFullCellRender="{current: dayjs}" | - |
| disabledDate | 不可选择的日期 | (currentDate: dayjs) => boolean | - |
| fullscreen | 是否全屏显示 | boolean | true |
| headerRender | 自定义头部内容 | v-slot:headerRender="{value: dayjs, type: string, onChange: f(), onTypeChange: f()}" | - |
| locale | 国际化配置 | object | 默认配置 |
| mode | 初始模式,month/year | string | month |
| monthCellRender | 作用域插槽,自定义渲染月单元格,返回内容会被追加到单元格 | v-slot:monthCellRender="{current: dayjs}" | - |
| monthFullCellRender | 作用域插槽,自定义渲染月单元格,返回内容覆盖单元格 | v-slot:monthFullCellRender="{current: dayjs}" | - |
| validRange | 设置可以显示的日期 | [dayjs, dayjs] | - |
| value(v-model) | 展示日期 | dayjs | 当前日期 |
| valueFormat | 可选,绑定值的格式,对 value、defaultValue 起作用。不指定则绑定值为 dayjs 对象 | string,具体格式 | - |
事件
| 事件名称 | 说明 | 回调参数 |
|---|---|---|
| change | 日期变化时的回调, 面板变化有可能导致日期变化 | function(date: dayjs | string) |
| panelChange | 日期面板变化回调 | function(date: dayjs | string, mode: string) |
| select | 选择日期回调,包含来源信息 | function(date: Dayjs, info: { source: 'year' | 'month' |
如何仅获取来自面板点击的日期?
select 事件提供额外的来源信息,你可以通过 info.source 来判断来源:
vue
<script lang="ts" setup>
const onSelect = (date, { source }) => {
if (source === 'date') {
console.log('Panel Select:', source);
}
};
</script>
<template>
<a-calendar @select="onSelect" />
</template>
