Vue纯JS实现日历
2020-03-12 本文已影响0人
西瓜鱼仔
效果图
不说废话,先上效果图:
实现代码
<template>
<div class="calender">
<div class="top">
<img src="./last-year.png" @click="handleShowLastYear"/>
<img src="./last-month.png" style="margin-left: 50px" @click="handleShowLastMonth"/>
<span class="top_date">{{year}}年{{month}}月</span>
<img src="./next-month.png" style="margin-left: 40px" @click="handleShowNextMonth"/>
<img src="./next-year.png" style="margin-left: 50px" @click="handleShowNextYear"/>
</div>
<div class="date_wrap">
<div class="week">
<span>日</span>
<span>一</span>
<span>二</span>
<span>三</span>
<span>四</span>
<span>五</span>
<span>六</span>
</div>
<div class="day">
<span v-for="(item,index) in lastDays" :key=index class="otherDay">
{{item}}
</span>
<span v-for="(item,index) in days" :key=index+50
:class="{current:currentDay===year.toString()+month.toString()+item}">
{{item}}
</span>
<span v-for="(item,index) in nextDays" :key=index+100 class="otherDay">
{{item}}
</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'calender',
data() {
return {
year: '',
month: '',
lastDays: [],
days: [],
nextDays: [],
currentDay: '',
}
},
methods: {
//控制当前日期显示特殊样式
handleShowDateStyle() {
let now = new Date();
this.currentDay = now.getFullYear().toString() + (now.getMonth() + 1).toString() + now.getDate().toString()
},
//获取当前年月份天数
getDays(Y, M) {
return new Date(Y, M, 0).getDate();
},
//得到当前年,这个月的一号是周几
getWeek(Y, M) {
let now = new Date();
now.setFullYear(this.year);
now.setMonth(this.month - 1);
now.setDate(1);
return now.getDay();
},
pushDays() {
//为了完整和美观,日历展示为7列*6行,一共展示42天
//将这个月多少天加入数组days
for (let i = 1; i <= this.getDays(this.year, this.month); i++) {
this.days.push(i)
}
//将上个月后面天数加入数组lastDays
for (let i = 0; i < this.getWeek(this.year, this.month); i++) {
let lastMonthDays = this.getDays(this.year, this.month - 1);
this.lastDays.unshift(lastMonthDays - i)
}
//将下个月前几天加入数组nextDays
let _length = this.days.length + this.lastDays.length;
for (let i = 1; i < 43 - _length; i++) {
this.nextDays.push(i)
}
},
getDate() {
let now = new Date();
this.year = now.getFullYear();
this.month = now.getMonth() + 1;
this.pushDays();
},
handleShowNextMonth() {
this.lastDays = [];
this.days = [];
this.nextDays = [];
if (this.month < 12) {
this.month = this.month + 1;
this.pushDays();
} else {
this.month = this.month = 1;
this.year = this.year + 1;
this.pushDays();
}
},
handleShowLastMonth() {
this.lastDays = [];
this.days = [];
this.nextDays = [];
if (this.month > 1) {
this.month = this.month - 1;
this.pushDays();
} else if (this.year > 1970) {
this.month = 12;
this.year = this.year - 1;
this.pushDays();
} else {
alert("不支持查找1970年之前的日期!")
}
},
handleShowNextYear() {
this.lastDays = [];
this.days = [];
this.nextDays = [];
this.year = this.year + 1;
this.pushDays();
},
handleShowLastYear() {
this.lastDays = [];
this.days = [];
this.nextDays = [];
if (this.year > 1970) {
this.year = this.year - 1;
this.pushDays();
} else {
alert("不支持查找1970年之前的日期!")
}
}
},
mounted() {
this.getDate();
this.handleShowDateStyle();
}
}
</script>
<style scoped>
.calender {
width: 600px;
}
.top {
width: 400px;
height: 30px;
line-height: 30px;
margin-left: 120px;
}
.top_date {
width: 100px;
font-size: 18px;
color: #2d8cf0;
margin-left: 40px;
}
.date_wrap {
margin-top: 12px;
}
.week {
width: 100%;
font-size: 17px;
font-weight: 500;
display: flex;
margin-left: 15px;
}
.week span {
margin-left: 51px;
}
.day {
display: flex;
width: 480px;
flex-direction: row;
font-size: 16px;
flex-wrap: wrap;
margin-left: 38px;
}
.day span {
margin-top: 13px;
width: 14.28%;
text-align: center;
}
.current {
color: #2d8cf0;
font-weight: bold;
}
.current:after {
content: "";
display: block;
width: 16px;
border-bottom: #2d8cf0 2px solid;
margin: 0 auto;
}
.otherDay {
color: #c5c8ce;
}
</style>
核心方法是pushDays()
思路
为了日历的完整和美观,采用的6行 × 7列,共42天的布局
- 首先计算出本月的天数以及本月1号是周几(1号永远在日历的第1行)
- 根据本月1号是周几,填充本月1号前面的空位
- 将本月日期填充进去
- 计算剩余空位,填充日历最后面的空位
素材
日历中切换年月的图标素材如下:
last-year.png
next-year.png
last-month.png
next-month.png