Vue实现日历日程
Vue 实现日历日程
使用第三方库(如 FullCalendar)
FullCalendar 是一个功能强大的日历库,支持 Vue 集成。安装依赖:
npm install @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction
引入并配置组件:
<template>
<FullCalendar :options="calendarOptions" />
</template>
<script>
import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction'
export default {
components: { FullCalendar },
data() {
return {
calendarOptions: {
plugins: [dayGridPlugin, interactionPlugin],
initialView: 'dayGridMonth',
events: [
{ title: '会议', start: '2023-10-10' },
{ title: '出差', start: '2023-10-15', end: '2023-10-17' }
],
dateClick: this.handleDateClick,
eventClick: this.handleEventClick
}
}
},
methods: {
handleDateClick(arg) {
alert('点击日期: ' + arg.dateStr)
},
handleEventClick(arg) {
alert('点击事件: ' + arg.event.title)
}
}
}
</script>
自定义日历组件
如果不需要复杂功能,可以手动实现基础日历。以下是一个简单示例:
<template>
<div class="calendar">
<div class="header">
<button @click="prevMonth">上个月</button>
<h3>{{ currentYear }}年{{ currentMonth + 1 }}月</h3>
<button @click="nextMonth">下个月</button>
</div>
<div class="days">
<div v-for="day in days" :key="day" class="day-header">{{ day }}</div>
</div>
<div class="dates">
<div
v-for="date in visibleDates"
:key="date.date"
:class="['date', { 'current-month': date.isCurrentMonth }]"
@click="selectDate(date)"
>
{{ date.date }}
<div v-if="hasEvent(date)" class="event-dot"></div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
days: ['日', '一', '二', '三', '四', '五', '六'],
currentYear: new Date().getFullYear(),
currentMonth: new Date().getMonth(),
events: [
{ date: '2023-10-15', title: '项目会议' },
{ date: '2023-10-20', title: '团队聚餐' }
]
}
},
computed: {
visibleDates() {
const dates = []
const firstDay = new Date(this.currentYear, this.currentMonth, 1)
const lastDay = new Date(this.currentYear, this.currentMonth + 1, 0)
// 上个月末尾几天
const prevMonthDays = firstDay.getDay()
for (let i = prevMonthDays - 1; i >= 0; i--) {
const date = new Date(this.currentYear, this.currentMonth, -i)
dates.push({
date: date.getDate(),
fullDate: date,
isCurrentMonth: false
})
}
// 当前月
for (let i = 1; i <= lastDay.getDate(); i++) {
const date = new Date(this.currentYear, this.currentMonth, i)
dates.push({
date: i,
fullDate: date,
isCurrentMonth: true
})
}
// 下个月开头几天
const nextMonthDays = 6 - lastDay.getDay()
for (let i = 1; i <= nextMonthDays; i++) {
const date = new Date(this.currentYear, this.currentMonth + 1, i)
dates.push({
date: date.getDate(),
fullDate: date,
isCurrentMonth: false
})
}
return dates
}
},
methods: {
prevMonth() {
if (this.currentMonth === 0) {
this.currentYear--
this.currentMonth = 11
} else {
this.currentMonth--
}
},
nextMonth() {
if (this.currentMonth === 11) {
this.currentYear++
this.currentMonth = 0
} else {
this.currentMonth++
}
},
selectDate(date) {
if (date.isCurrentMonth) {
console.log('选中日期:', date.fullDate)
}
},
hasEvent(date) {
if (!date.isCurrentMonth) return false
const dateStr = date.fullDate.toISOString().split('T')[0]
return this.events.some(event => event.date === dateStr)
}
}
}
</script>
<style>
.calendar {
width: 100%;
max-width: 600px;
margin: 0 auto;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.days {
display: grid;
grid-template-columns: repeat(7, 1fr);
text-align: center;
}
.dates {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.date {
aspect-ratio: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 4px;
}
.date.current-month {
background: #f0f0f0;
}
.date:hover {
background: #e0e0e0;
}
.event-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #f00;
margin-top: 2px;
}
</style>
功能扩展建议
- 添加事件表单:点击日期弹出表单,允许用户添加/编辑日程
- 持久化存储:将日程数据保存到 localStorage 或后端数据库
- 周视图切换:支持按月/周/日不同维度查看日程
- 拖拽功能:实现事件拖拽调整时间
- 颜色分类:为不同类型的事件设置不同颜色标识
两种方案各有优劣:第三方库功能全面但体积较大;自定义组件更轻量但需要手动实现更多功能。可根据项目需求选择合适方案。







