vue实现年历标记
实现年历标记的基本思路
在Vue中实现年历标记功能,通常需要结合日期处理库(如dayjs或date-fns)和动态渲染逻辑。核心步骤包括生成全年日期数据、标记特定日期、以及渲染交互式日历界面。
安装依赖库
推荐使用dayjs处理日期:
npm install dayjs
生成全年日期数据
通过dayjs生成当前年份的月份和日期数据:
import dayjs from 'dayjs';
export default {
data() {
return {
currentYear: dayjs().year(),
markedDates: ['2023-05-20', '2023-11-15'] // 示例标记日期
}
},
computed: {
yearCalendar() {
const months = [];
for (let month = 0; month < 12; month++) {
const daysInMonth = dayjs().year(this.currentYear).month(month).daysInMonth();
const monthDays = [];
for (let day = 1; day <= daysInMonth; day++) {
const date = dayjs().year(this.currentYear).month(month).date(day);
monthDays.push({
date: date.format('YYYY-MM-DD'),
isMarked: this.markedDates.includes(date.format('YYYY-MM-DD'))
});
}
months.push({
monthName: dayjs().month(month).format('MMMM'),
days: monthDays
});
}
return months;
}
}
}
渲染日历界面
使用v-for渲染月份和日期格子,并通过CSS标记特殊日期:
<template>
<div class="year-calendar">
<div v-for="(month, index) in yearCalendar" :key="index" class="month">
<h3>{{ month.monthName }}</h3>
<div class="days-grid">
<div
v-for="(day, dayIndex) in month.days"
:key="dayIndex"
:class="['day', { 'marked': day.isMarked }]"
>
{{ dayjs(day.date).date() }}
</div>
</div>
</div>
</div>
</template>
<style>
.year-calendar {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.month {
border: 1px solid #eee;
padding: 10px;
}
.days-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.day {
height: 30px;
display: flex;
align-items: center;
justify-content: center;
}
.marked {
background-color: #ffeb3b;
border-radius: 50%;
}
</style>
添加交互功能
实现日期点击标记/取消标记:
methods: {
toggleMark(date) {
const index = this.markedDates.indexOf(date);
if (index === -1) {
this.markedDates.push(date);
} else {
this.markedDates.splice(index, 1);
}
}
}
在模板中添加点击事件:
<div
@click="toggleMark(day.date)"
:class="['day', { 'marked': day.isMarked }]"
>
{{ dayjs(day.date).date() }}
</div>
高级功能扩展
支持不同类型的标记(如节假日、纪念日):
data() {
return {
markTypes: {
holiday: { color: '#f44336', text: '休' },
event: { color: '#4caf50', text: '事' }
},
customMarks: {
'2023-10-01': { type: 'holiday', note: '国庆节' },
'2023-08-08': { type: 'event', note: '项目截止' }
}
}
}
渲染时根据类型显示不同样式:
<div
v-for="(day, dayIndex) in month.days"
:key="dayIndex"
:class="['day', customMarks[day.date]?.type]"
:style="{ backgroundColor: customMarks[day.date] ? markTypes[customMarks[day.date].type].color : '' }"
>
{{ dayjs(day.date).date() }}
<span v-if="customMarks[day.date]">
{{ markTypes[customMarks[day.date].type].text }}
</span>
</div>


