vue页面实现日历
实现基础日历布局
使用Vue的模板语法构建日历的基本HTML结构,通常需要包含星期标题和日期格子。月份切换按钮可以通过v-on绑定事件。
<template>
<div class="calendar">
<div class="header">
<button @click="prevMonth">上个月</button>
<h2>{{ currentYear }}年{{ currentMonth + 1 }}月</h2>
<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="(day, index) in days"
:key="index"
:class="{ 'other-month': !day.isCurrentMonth }"
>
{{ day.date }}
</div>
</div>
</div>
</template>
处理日历数据逻辑
在Vue的data或setup中定义日历所需的状态,并通过计算属性生成当前月份的日期数组。需要考虑上个月和下个月的残留日期。
<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)
const lastDay = new Date(year, month + 1, 0)
const days = []
// 上个月残留日期
const prevMonthDays = firstDay.getDay()
for (let i = prevMonthDays - 1; i >= 0; i--) {
days.push({
date: new Date(year, month, -i).getDate(),
isCurrentMonth: false
})
}
// 当前月日期
for (let i = 1; i <= lastDay.getDate(); i++) {
days.push({
date: i,
isCurrentMonth: true
})
}
// 下个月残留日期
const nextMonthDays = 6 - lastDay.getDay()
for (let i = 1; i <= nextMonthDays; 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)
}
}
}
</script>
添加样式美化日历
使用CSS为日历添加基本样式,包括格子布局、当前月和其他月日期的不同样式等。

<style scoped>
.calendar {
width: 350px;
margin: 0 auto;
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;
padding: 5px;
}
.days div {
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}
.days div.other-month {
color: #ccc;
}
.days div:hover {
background-color: #f0f0f0;
cursor: pointer;
}
</style>
添加日期选择功能
扩展基础日历,添加日期选择功能。通过v-model或自定义事件实现与父组件的通信。
// 在data中添加
selectedDate: null,
// 在methods中添加
selectDate(day) {
if (day.isCurrentMonth) {
this.selectedDate = new Date(this.currentYear, this.currentMonth, day.date)
this.$emit('date-selected', this.selectedDate)
}
}
// 在模板中修改days部分
<div
v-for="(day, index) in days"
:key="index"
:class="{
'other-month': !day.isCurrentMonth,
'selected': selectedDate && selectedDate.getDate() === day.date
&& selectedDate.getMonth() === currentMonth
&& selectedDate.getFullYear() === currentYear
}"
@click="selectDate(day)"
>
{{ day.date }}
</div>
使用第三方库简化开发
对于更复杂的需求,可以考虑使用专门的Vue日历组件库,如v-calendar或vue-datepicker。

安装v-calendar:
npm install v-calendar
基本使用示例:
import { Calendar } from 'v-calendar'
export default {
components: {
Calendar
},
data() {
return {
attributes: [
{
key: 'today',
highlight: {
color: 'blue',
fillMode: 'light'
},
dates: new Date()
}
]
}
}
}
模板部分:
<Calendar
:attributes="attributes"
@dayclick="dayClicked"
/>
这种方法可以快速实现高级功能如范围选择、多日期选择、自定义样式等,减少自行开发的复杂度。






