vue VUE实现日历组件功能
实现日历组件的基本思路
日历组件的核心是动态生成日期表格,并处理用户交互(如点击日期、切换月份)。Vue的响应式数据和组件化特性非常适合实现这一功能。
核心代码实现
模板部分(Calendar.vue)
<template>
<div class="calendar">
<div class="header">
<button @click="prevMonth">上个月</button>
<span>{{ currentYear }}年{{ currentMonth + 1 }}月</span>
<button @click="nextMonth">下个月</button>
</div>
<div class="weekdays">
<div v-for="day in weekdays" :key="day">{{ day }}</div>
</div>
<div class="days">
<div
v-for="(date, index) in days"
:key="index"
:class="{
'other-month': !date.isCurrentMonth,
'today': date.isToday,
'selected': date.isSelected
}"
@click="selectDate(date)"
>
{{ date.day }}
</div>
</div>
</div>
</template>
脚本部分
<script>
export default {
data() {
return {
weekdays: ['日', '一', '二', '三', '四', '五', '六'],
currentDate: new Date(),
selectedDate: null
}
},
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)
const lastDay = new Date(year, month + 1, 0)
// 获取当月天数
const daysInMonth = lastDay.getDate()
// 获取第一天是星期几
const firstDayOfWeek = firstDay.getDay()
// 生成日期数组
const days = []
// 添加上个月末尾的几天
const prevMonthLastDay = new Date(year, month, 0).getDate()
for (let i = 0; i < firstDayOfWeek; i++) {
days.push({
day: prevMonthLastDay - firstDayOfWeek + i + 1,
isCurrentMonth: false,
date: new Date(year, month - 1, prevMonthLastDay - firstDayOfWeek + 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.getDate() === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear(),
isSelected: this.selectedDate &&
date.getDate() === this.selectedDate.getDate() &&
date.getMonth() === this.selectedDate.getMonth() &&
date.getFullYear() === this.selectedDate.getFullYear(),
date: date
})
}
// 添加下个月开始的几天
const daysNeeded = 42 - days.length // 6行x7列
for (let i = 1; i <= daysNeeded; i++) {
days.push({
day: i,
isCurrentMonth: false,
date: new Date(year, month + 1, i)
})
}
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)
},
selectDate(date) {
this.selectedDate = date.date
this.$emit('date-selected', date.date)
}
}
}
</script>
样式部分

<style scoped>
.calendar {
width: 300px;
font-family: Arial, sans-serif;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.weekdays, .days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.weekdays div {
text-align: center;
font-weight: bold;
}
.days div {
height: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 50%;
}
.days div:hover {
background-color: #eee;
}
.other-month {
color: #ccc;
}
.today {
background-color: #e6f7ff;
font-weight: bold;
}
.selected {
background-color: #1890ff;
color: white;
}
</style>
功能扩展建议
-
多语言支持 添加i18n支持,可切换不同语言的星期显示。
-
日期范围选择 修改逻辑支持选择开始日期和结束日期。

-
事件标记 允许在特定日期上显示标记点或自定义内容。
-
禁用日期 添加逻辑禁用不可选的日期(如过去的日期)。
-
自定义样式 通过props暴露更多样式定制选项。
使用示例
<template>
<div>
<Calendar @date-selected="handleDateSelected" />
<p v-if="selectedDate">选中的日期: {{ selectedDate.toLocaleDateString() }}</p>
</div>
</template>
<script>
import Calendar from './Calendar.vue'
export default {
components: {
Calendar
},
data() {
return {
selectedDate: null
}
},
methods: {
handleDateSelected(date) {
this.selectedDate = date
}
}
}
</script>
这个实现提供了基本的日历功能,包括月份切换、日期选择和当天高亮。根据具体需求可以进一步扩展功能。






