vue实现日历组件
实现基础日历结构
使用Vue的模板语法构建日历的基本HTML结构,包括星期标题和日期格子。通过v-for循环渲染日期,动态绑定类名控制样式。
<template>
<div class="calendar">
<div class="header">
<span v-for="day in weekDays" :key="day">{{ day }}</span>
</div>
<div class="days">
<span
v-for="(date, index) in days"
:key="index"
:class="{ 'current-month': date.isCurrentMonth, 'today': date.isToday }"
@click="selectDate(date)"
>
{{ date.day }}
</span>
</div>
</div>
</template>
处理日期数据逻辑
在Vue组件的script部分定义计算属性,生成当前月份的所有日期数据。包括上个月残留日期、本月日期和下个月补全日期。

<script>
export default {
data() {
return {
currentDate: new Date(),
weekDays: ['日', '一', '二', '三', '四', '五', '六']
}
},
computed: {
days() {
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)
const daysInMonth = lastDay.getDate()
const startDay = firstDay.getDay()
const endDay = lastDay.getDay()
const daysFromPrevMonth = startDay
const daysFromNextMonth = 6 - endDay
const days = []
// 添加上个月末尾日期
const prevMonthLastDay = new Date(year, month, 0).getDate()
for (let i = daysFromPrevMonth; i > 0; i--) {
days.push({
day: prevMonthLastDay - i + 1,
isCurrentMonth: false,
date: new Date(year, month - 1, prevMonthLastDay - i + 1)
})
}
// 添加本月日期
const today = new Date()
for (let i = 1; i <= daysInMonth; i++) {
const date = new Date(year, month, i)
days.push({
day: i,
isCurrentMonth: true,
isToday: date.toDateString() === today.toDateString(),
date: date
})
}
// 添加下个月开始日期
for (let i = 1; i <= daysFromNextMonth; i++) {
days.push({
day: i,
isCurrentMonth: false,
date: new Date(year, month + 1, i)
})
}
return days
}
}
}
</script>
添加月份切换功能
实现上个月和下个月切换的方法,更新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.$emit('date-selected', date)
}
}
添加样式美化
为日历组件添加基本CSS样式,使布局更美观。使用CSS Grid布局日期格子,添加悬停和选中状态效果。

<style scoped>
.calendar {
width: 350px;
font-family: Arial;
}
.header {
display: grid;
grid-template-columns: repeat(7, 1fr);
text-align: center;
font-weight: bold;
margin-bottom: 10px;
}
.days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.days span {
padding: 8px;
text-align: center;
cursor: pointer;
border-radius: 4px;
}
.days span.current-month {
background: #fff;
}
.days span:not(.current-month) {
color: #ccc;
}
.days span.today {
background: #e6f7ff;
font-weight: bold;
}
.days span:hover {
background: #f0f0f0;
}
</style>
扩展功能建议
对于更复杂的日历组件,可以考虑添加以下功能:
- 支持多语言星期显示
- 添加事件标记功能
- 实现日期范围选择
- 支持自定义主题颜色
- 添加周视图和日视图切换
- 集成日期选择器输入框
组件使用时通过v-model绑定当前日期,监听date-selected事件处理日期选择。
<calendar
v-model="selectedDate"
@date-selected="handleDateSelect"
/>






