vue实现日历效果
实现基础日历布局
使用Vue的模板语法构建日历的基本HTML结构,通常包括星期标题栏和日期格子。通过v-for循环生成日期单元格,动态绑定样式类以标记当前月、非当前月或选中日期。
<template>
<div class="calendar">
<div class="weekdays">
<span v-for="day in weekdays" :key="day">{{ day }}</span>
</div>
<div class="days">
<span
v-for="(date, index) in visibleDates"
:key="index"
:class="{ 'other-month': !date.isCurrentMonth, 'today': date.isToday }"
@click="selectDate(date)"
>
{{ date.day }}
</span>
</div>
</div>
</template>
处理日期数据逻辑
在Vue组件的data或computed中定义日期生成逻辑。计算当前月份的首日位置和总天数,生成包含日期对象(含月份标记)的数组。
export default {
data() {
return {
currentDate: new Date(),
weekdays: ['日', '一', '二', '三', '四', '五', '六']
}
},
computed: {
visibleDates() {
const year = this.currentDate.getFullYear();
const month = this.currentDate.getMonth();
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
// 生成当前月日期
let dates = [];
for (let day = 1; day <= lastDay.getDate(); day++) {
dates.push({
day,
date: new Date(year, month, day),
isCurrentMonth: true
});
}
// 补全上月和下月日期
const startDay = firstDay.getDay();
const endDay = lastDay.getDay();
const prevMonthDays = new Date(year, month, 0).getDate();
for (let i = 0; i < startDay; i++) {
dates.unshift({
day: prevMonthDays - i,
date: new Date(year, month - 1, prevMonthDays - i),
isCurrentMonth: false
});
}
for (let i = 1; i <= 6 - endDay; i++) {
dates.push({
day: i,
date: new Date(year, month + 1, i),
isCurrentMonth: false
});
}
return dates;
}
}
}
添加交互功能
实现月份切换和日期选择功能,通过方法更新currentDate触发响应式重新计算。添加事件处理函数处理用户点击日期时的逻辑。

methods: {
prevMonth() {
this.currentDate = new Date(
this.currentDate.getFullYear(),
this.currentDate.getMonth() - 1,
1
);
},
nextMonth() {
this.currentDate = new Date(
this.currentDate.getFullYear(),
this.currentDate.getMonth() + 1,
1
);
},
selectDate(date) {
this.selectedDate = date;
// 触发自定义事件或处理业务逻辑
this.$emit('date-selected', date);
}
}
样式优化
使用CSS Grid布局实现日历的整齐排列,添加悬停和选中状态样式提升用户体验。
.calendar {
width: 100%;
max-width: 400px;
margin: 0 auto;
}
.weekdays, .days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 8px;
}
.days span {
padding: 8px;
text-align: center;
cursor: pointer;
border-radius: 4px;
}
.days span:hover {
background-color: #f0f0f0;
}
.other-month {
color: #ccc;
}
.today {
background-color: #e3f2fd;
}
.selected {
background-color: #2196f3;
color: white;
}
进阶功能扩展
添加事件标记 在日期对象中增加事件数据,通过模板条件渲染显示事件标记点。

dates = dates.map(date => ({
...date,
hasEvent: checkIfHasEvent(date.date) // 自定义事件检查函数
}));
<span v-if="date.hasEvent" class="event-dot"></span>
支持范围选择 通过记录开始和结束日期,在计算属性中判断每个日期是否处于选中范围内,动态添加样式类。
isInRange(date) {
if (!this.startDate || !this.endDate) return false;
return date >= this.startDate && date <= this.endDate;
}
国际化支持
动态切换星期显示和月份名称,使用Intl.DateTimeFormatAPI根据语言环境格式化日期。
const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short' });
this.weekdays = Array.from({ length: 7 }, (_, i) =>
formatter.format(new Date(2023, 0, i + 1))
);






