vue 实现日历
实现基础日历结构
使用 Vue 的模板和计算属性构建日历骨架。通过 v-for 循环渲染月份和日期格子,动态绑定样式类控制选中状态。
<template>
<div class="calendar">
<div class="header">
<button @click="prevMonth">上一月</button>
<span>{{ currentYear }}年{{ currentMonth + 1 }}月</span>
<button @click="nextMonth">下一月</button>
</div>
<div class="days">
<div v-for="day in ['日', '一', '二', '三', '四', '五', '六']" :key="day">{{ day }}</div>
</div>
<div class="dates">
<div
v-for="date in visibleDates"
:key="date.date"
:class="{ 'other-month': !date.isCurrentMonth, 'selected': date.isSelected }"
@click="selectDate(date)"
>
{{ date.day }}
</div>
</div>
</div>
</template>
处理日期逻辑
通过 JavaScript 的 Date 对象计算当前月份的天数、上月残留天数及下月补全天数,生成完整的日历数组。
<script>
export default {
data() {
return {
currentDate: new Date(),
selectedDate: null
};
},
computed: {
currentYear() {
return this.currentDate.getFullYear();
},
currentMonth() {
return this.currentDate.getMonth();
},
visibleDates() {
const year = this.currentYear;
const month = this.currentMonth;
const firstDay = new Date(year, month, 1).getDay();
const daysInMonth = new Date(year, month + 1, 0).getDate();
const daysFromPrevMonth = firstDay;
const daysFromNextMonth = 6 - new Date(year, month, daysInMonth).getDay();
const dates = [];
// 上月日期
const prevMonthDays = new Date(year, month, 0).getDate();
for (let i = daysFromPrevMonth - 1; i >= 0; i--) {
dates.push({
day: prevMonthDays - i,
isCurrentMonth: false,
date: new Date(year, month - 1, prevMonthDays - i)
});
}
// 当月日期
for (let i = 1; i <= daysInMonth; i++) {
dates.push({
day: i,
isCurrentMonth: true,
date: new Date(year, month, i)
});
}
// 下月日期
for (let i = 1; i <= daysFromNextMonth; i++) {
dates.push({
day: i,
isCurrentMonth: false,
date: new Date(year, month + 1, i)
});
}
return dates;
}
},
methods: {
prevMonth() {
this.currentDate = new Date(this.currentYear, this.currentMonth - 1, 1);
},
nextMonth() {
this.currentDate = new Date(this.currentYear, this.currentMonth + 1, 1);
},
selectDate(date) {
this.selectedDate = date.date;
}
}
};
</script>
添加样式优化
通过 CSS 美化日历布局,高亮当前选中日期和非当月日期。

<style scoped>
.calendar {
width: 300px;
border: 1px solid #eee;
font-family: Arial, sans-serif;
}
.header {
display: flex;
justify-content: space-between;
padding: 10px;
background: #f5f5f5;
}
.days {
display: grid;
grid-template-columns: repeat(7, 1fr);
text-align: center;
background: #f0f0f0;
}
.dates {
display: grid;
grid-template-columns: repeat(7, 1fr);
text-align: center;
}
.dates div {
padding: 10px;
cursor: pointer;
}
.other-month {
color: #ccc;
}
.selected {
background: #42b983;
color: white;
}
</style>
扩展功能建议
- 事件标记:在日期格子中显示自定义事件图标或文字。
- 范围选择:通过
mouseenter和mouseleave事件实现日期区间选择。 - 国际化:支持多语言星期显示,使用
Intl.DateTimeFormat处理。
完整代码可结合 Vue 3 的 Composition API 重构,逻辑更清晰。






