vue周日历组件, 支持自定义样式
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ba2009c7a9404e3ca9d385a1aef517f2.png#pic_center)
1. 安装
npm i date-fns --save
2. 定义组件
<template>
<div class="weekly-calendar">
<p class="weekTitle">{{ showMonth }}</p>
<div class="days">
<div class="day-labels">
<div class="el-icon-arrow-left" @click="prevWeek"></div>
<div class="day-label">一</div>
<div class="day-label">二</div>
<div class="day-label">三</div>
<div class="day-label">四</div>
<div class="day-label">五</div>
<div class="day-label">六</div>
<div class="day-label">日</div>
<div class="el-icon-arrow-right" @click="nextWeek"></div>
</div>
<div class="day-cells">
<div
class="day-cell"
v-for="(day, index) in days"
:key="index"
:class="{ today: (isToday(day) && !checkIndex) || checkIndex == index, 'not-in-month': !isInMonth(day) }"
>
<div class="day-number" @click="clickDays(index, day)">{{ isToday(day) ? '今天' : format(day, 'dd') }}</div>
<div class="day-dot"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import { format } from 'date-fns';
export default {
data() {
return {
currentWeek: {
start: null,
end: null,
},
checkIndex: null,
showMonth: null,
};
},
computed: {
days() {
const days = [];
const weekStart = this.currentWeek.start;
const weekEnd = this.currentWeek.end;
const diff = (weekEnd.getTime() - weekStart.getTime()) / (24 * 60 * 60 * 1000);
for (let i = 0; i <= diff; i++) {
const day = new Date(weekStart.getTime() + i * 24 * 60 * 60 * 1000);
days.push(day);
}
return days;
},
},
methods: {
format,
clickDays(index, day) {
this.checkIndex = index;
this.seShowMonth(day);
},
prevWeek() {
this.checkDay = null;
const firstDayOfWeek = 1;
const weekStart = this.currentWeek.start;
const prevWeekStart = new Date(weekStart.getTime() - 7 * 24 * 60 * 60 * 1000);
this.currentWeek.start = new Date(prevWeekStart.getTime() - (prevWeekStart.getDay() - firstDayOfWeek) * 24 * 60 * 60 * 1000);
this.currentWeek.end = new Date(this.currentWeek.start.getTime() + 6 * 24 * 60 * 60 * 1000);
this.checkIndex = 3;
const day = new Date(this.currentWeek.end.getTime() - 3 * 24 * 60 * 60 * 1000);
this.seShowMonth(day);
},
nextWeek() {
this.checkDay = null;
const firstDayOfWeek = 0;
const weekEnd = this.currentWeek.end;
const nextWeekEnd = new Date(weekEnd.getTime() + 7 * 24 * 60 * 60 * 1000);
this.currentWeek.end = new Date(nextWeekEnd.getTime() + (firstDayOfWeek - nextWeekEnd.getDay()) * 24 * 60 * 60 * 1000);
this.currentWeek.start = new Date(this.currentWeek.end.getTime() - 6 * 24 * 60 * 60 * 1000);
this.checkIndex = 3;
const day = new Date(this.currentWeek.start.getTime() + 3 * 24 * 60 * 60 * 1000);
this.seShowMonth(day);
},
isToday(date) {
const today = new Date();
return date.toDateString() === today.toDateString();
},
isInMonth(date) {
return format(date, 'yyyy/MM') == this.showMonth;
},
seShowMonth(day) {
this.showMonth = format(day, 'yyyy/MM');
},
setToday() {
const firstDayOfWeek = 1;
const today = new Date();
const currentWeekStart = new Date(today.getTime() - (today.getDay() - firstDayOfWeek) * 24 * 60 * 60 * 1000);
this.currentWeek.start = currentWeekStart;
this.currentWeek.end = new Date(currentWeekStart.getTime() + 6 * 24 * 60 * 60 * 1000);
this.seShowMonth(this.currentWeek.start);
},
},
created() {
this.setToday();
},
};
</script>
<style scoped>
.weekly-calendar {
max-width: 500px;
margin: 0 auto;
font-family: Arial, sans-serif;
padding: 0 20px;
margin-bottom: 20px;
}
.weekly-calendar .weekTitle {
text-align: left;
font-size: 16px;
font-family: PingFang SC, PingFang SC-Semibold;
font-weight: 600;
color: #000000;
}
.weekly-calendar .controls {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.weekly-calendar .day-labels {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.weekly-calendar .day-label {
flex: 1;
text-align: center;
opacity: 0.52;
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
color: #333333;
}
.weekly-calendar .day-cells {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 0 15px;
}
.weekly-calendar .day-cell {
flex: 1;
padding: 10px;
text-align: center;
font-size: 16px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
color: #000000;
cursor: pointer;
position: relative;
}
.weekly-calendar .day-dot {
position: absolute;
top: 5px;
right: 14px;
width: 4px;
height: 4px;
background: #1c9eff;
border-radius: 50%;
}
.weekly-calendar .day-number {
z-index: 6;
position: relative;
}
.weekly-calendar .today {
position: relative;
color: #fff;
}
.weekly-calendar .today::before {
content: '';
position: absolute;
left: calc(50% - 16px);
top: calc(50% - 16px);
width: 32px;
height: 32px;
background: #1c9eff;
border-radius: 50%;
z-index: 0;
}
.weekly-calendar .not-in-month {
color: #ccc;
}
</style>