vue 实现日历
实现基础日历结构
使用 Vue 的模板语法构建日历的网格布局,通常以 7 列(一周)和 5-6 行(月份天数)的表格形式展示。通过 v-for 循环渲染日期单元格,动态绑定样式和事件。
<template>
<div class="calendar">
<div class="header">
<button @click="prevMonth">上一月</button>
<h3>{{ currentYear }}年{{ currentMonth + 1 }}月</h3>
<button @click="nextMonth">下一月</button>
</div>
<div class="weekdays">
<span v-for="day in weekdays" :key="day">{{ day }}</span>
</div>
<div class="days">
<span
v-for="(day, index) in days"
:key="index"
:class="{ 'other-month': !day.isCurrentMonth, 'today': day.isToday }"
@click="selectDay(day)">
{{ day.date }}
</span>
</div>
</div>
</template>
处理日期逻辑
通过 JavaScript 的 Date 对象计算当前月份的天数、起始星期以及上个月/下个月的残留日期。核心逻辑包括:
- 获取月份第一天和最后一天的星期数。
- 生成包含当前月、上月残留和下月补全的日期数组。
<script>
export default {
data() {
return {
currentDate: new Date(),
weekdays: ['日', '一', '二', '三', '四', '五', '六']
};
},
computed: {
currentYear() {
return this.currentDate.getFullYear();
},
currentMonth() {
return this.currentDate.getMonth();
},
days() {
const year = this.currentYear;
const month = this.currentMonth;
const firstDay = new Date(year, month, 1).getDay();
const lastDate = new Date(year, month + 1, 0).getDate();
const prevLastDate = new Date(year, month, 0).getDate();
const days = [];
// 上月残留日期
for (let i = firstDay - 1; i >= 0; i--) {
days.push({
date: prevLastDate - i,
isCurrentMonth: false
});
}
// 当前月日期
for (let i = 1; i <= lastDate; i++) {
const today = new Date();
days.push({
date: i,
isCurrentMonth: true,
isToday: today.getDate() === i &&
today.getMonth() === month &&
today.getFullYear() === year
});
}
// 下月补全日期
const remaining = 42 - days.length;
for (let i = 1; i <= remaining; i++) {
days.push({
date: i,
isCurrentMonth: false
});
}
return days;
}
},
methods: {
prevMonth() {
this.currentDate = new Date(this.currentYear, this.currentMonth - 1, 1);
},
nextMonth() {
this.currentDate = new Date(this.currentYear, this.currentMonth + 1, 1);
},
selectDay(day) {
if (day.isCurrentMonth) {
console.log(`选中日期: ${this.currentYear}-${this.currentMonth + 1}-${day.date}`);
}
}
}
};
</script>
添加样式优化
通过 CSS 美化日历布局,区分当前月、非当前月及今日的样式。
<style scoped>
.calendar {
width: 300px;
border: 1px solid #eee;
font-family: Arial, sans-serif;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
background: #f5f5f5;
}
.weekdays, .days {
display: grid;
grid-template-columns: repeat(7, 1fr);
text-align: center;
}
.weekdays {
background: #ddd;
padding: 5px 0;
}
.days span {
padding: 10px;
cursor: pointer;
}
.other-month {
color: #ccc;
}
.today {
background: #4CAF50;
color: white;
border-radius: 50%;
}
</style>
扩展功能建议
- 事件标记:在日期单元格中显示自定义事件图标或文字。
- 范围选择:支持通过鼠标拖动选择日期范围。
- 国际化:根据地区动态切换星期显示顺序(如周一为首日)。
- 服务端集成:结合 API 拉取节假日或日程数据。
通过上述步骤,可实现一个基础的交互式 Vue 日历组件,后续可根据需求进一步扩展功能。







