vue 日历组件实现
Vue 日历组件实现
基本结构搭建
使用Vue的单文件组件(SFC)结构,创建一个基础的日历组件框架。需要定义月份、年份的状态管理,以及日期渲染逻辑。
<template>
<div class="calendar">
<div class="header">
<button @click="prevMonth">上一月</button>
<h2>{{ currentYear }}年{{ currentMonth }}月</h2>
<button @click="nextMonth">下一月</button>
</div>
<div class="days-grid">
<div v-for="day in days" :key="day" class="day-header">{{ day }}</div>
<div
v-for="date in visibleDates"
:key="date.getTime()"
class="date-cell"
:class="{ 'other-month': !isCurrentMonth(date) }"
>
{{ date.getDate() }}
</div>
</div>
</div>
</template>
核心逻辑实现
需要计算当前月份的所有日期,包括上个月和下个月的部分日期以确保日历网格完整。

<script>
export default {
data() {
return {
currentDate: new Date(),
days: ['日', '一', '二', '三', '四', '五', '六']
}
},
computed: {
currentYear() {
return this.currentDate.getFullYear()
},
currentMonth() {
return this.currentDate.getMonth() + 1
},
visibleDates() {
const dates = []
const firstDay = new Date(this.currentYear, this.currentDate.getMonth(), 1)
const lastDay = new Date(this.currentYear, this.currentDate.getMonth() + 1, 0)
// 上个月的最后几天
const prevMonthDays = firstDay.getDay()
for (let i = prevMonthDays - 1; i >= 0; i--) {
const date = new Date(firstDay)
date.setDate(date.getDate() - (i + 1))
dates.push(date)
}
// 当前月的所有日期
for (let i = 1; i <= lastDay.getDate(); i++) {
dates.push(new Date(this.currentYear, this.currentDate.getMonth(), i))
}
// 下个月的前几天
const nextMonthDays = 6 - lastDay.getDay()
for (let i = 1; i <= nextMonthDays; i++) {
const date = new Date(lastDay)
date.setDate(date.getDate() + i)
dates.push(date)
}
return dates
}
},
methods: {
isCurrentMonth(date) {
return date.getMonth() === this.currentDate.getMonth()
},
prevMonth() {
this.currentDate = new Date(this.currentYear, this.currentDate.getMonth() - 1, 1)
},
nextMonth() {
this.currentDate = new Date(this.currentYear, this.currentDate.getMonth() + 1, 1)
}
}
}
</script>
样式设计
为日历添加基本样式,确保布局合理美观。

<style scoped>
.calendar {
width: 100%;
max-width: 400px;
margin: 0 auto;
font-family: Arial, sans-serif;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.days-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.day-header {
text-align: center;
font-weight: bold;
padding: 5px;
}
.date-cell {
text-align: center;
padding: 10px;
border: 1px solid #eee;
cursor: pointer;
}
.date-cell:hover {
background-color: #f5f5f5;
}
.other-month {
color: #ccc;
}
</style>
功能扩展
可以添加日期选择功能,标记特定日期等高级功能。
// 在methods中添加
selectDate(date) {
this.$emit('date-selected', date)
}
// 在模板中修改date-cell
<div
v-for="date in visibleDates"
:key="date.getTime()"
class="date-cell"
:class="{
'other-month': !isCurrentMonth(date),
'selected': isSelected(date)
}"
@click="selectDate(date)"
>
{{ date.getDate() }}
</div>
// 添加isSelected方法
isSelected(date) {
return this.selectedDate &&
date.getDate() === this.selectedDate.getDate() &&
date.getMonth() === this.selectedDate.getMonth() &&
date.getFullYear() === this.selectedDate.getFullYear()
}
第三方库集成
对于更复杂的需求,可以考虑使用成熟的日历库如v-calendar或fullcalendar-vue。
npm install v-calendar
import VCalendar from 'v-calendar'
// 在main.js中
Vue.use(VCalendar)
// 组件中使用
<template>
<v-calendar />
</template>






