日历大概长这个样子, 两种颗粒度的。 有上月-到下月的周内日期补充。
平时要么就用插件要么扒网上的代码,也没存过每回都是现用现扒。所以想自己搞一个基础版的方便修改和调整,用vue写的,没用UI库. 代码如下
<template>
<div class="calendar">
<div class="calendar-header padding line-bottom flex justify-between">
<div class="heder-l">当前月份:{{ currentMonth }}</div>
<div class="heder-r flex align-center">
<div class="next-month line" @click="handleLastMonth">上个月</div>
<div class="next-month line" @click="handleNextMonth">下个月</div>
</div>
</div>
<div class="calendar-main padding-xl">
<div class="week flex">
<div class="week-box" v-for="item in weekData" :key="item">
{{ item }}
</div>
</div>
<div class="calendar-wrapper flex flex-wrap line-top line-left">
<div
class="calendar-box padding line-bottom line-right"
v-for="item in calendarData"
:key="item.currentDate"
:class="[
item.disabled ? 'disabled' : '',
item.currentDate == currentDate ? 'active' : '',
]"
@click="handleClickDate(item)"
>
{{ item.currentDate }}
</div>
</div>
</div>
</div>
</template>
<script>
var _Date = new Date();
var _year = _Date.getFullYear();
var _month = _Date.getMonth() + 1;
let _day = _Date.getDate();
export default {
props: {},
data() {
return {
value: new Date(),
weekData: ["一", "二", "三", "四", "五", "六", "日"], // 星期
currentMonth: "", //当前月份
currentDate: `${_year}-${_month}-${_day}`, //当前日期
calendarData: [], //当月日期集合
};
},
mounted() {
this.getFullMonth();
},
methods: {
/**
* 获取整月日期
*/
getFullMonth() {
this.currentMonth = `${_year}-${this.formatZero(_month)}`;
let currentMonthNum = new Date(_year, _month, 0).getDate(); // 获取当月总天数
let temaryDateArr = [];
//获取当月日期
for (let i = 1; i <= currentMonthNum; i++) {
let day = new Date(_year, _month, 0).setDate(i);
temaryDateArr.push(this.getCurrentDate(day));
}
// start 上月及下月的日期补充
let lastMonthArr = [];
let nextMonthArr = [];
let lastYear = _month == 1 ? _year - 1 : _year; // 上月年份(跨年)
let lastMonth = _month == 1 ? 12 : _month - 1; //上月月份(跨年)
let lastMonthNum = new Date(lastYear, lastMonth, 0).getDate(); // 上月总天数
let lastMonthSurplus = temaryDateArr[0].day - 1; // 上月需要补充的天数,(当前日期的星期数-1)
let lDate = new Date(`${lastYear}-${lastMonth}`); //上月Date对象
let nextYear = _month == 12 ? _year + 1 : _year; //下月年份(跨年)
let nextMonth = _month == 12 ? 1 : _month + 1; // 下月月份(跨年)
let nexMonthSurplus = 7 - temaryDateArr[temaryDateArr.length - 1].day; //下月需要补充的天数
let nDate = new Date(`${nextYear}-${nextMonth}`); // 下月Date对象
//上月日期补充列表
if (temaryDateArr[0].day > 1) {
for (let i = 1; i <= lastMonthSurplus; i++) {
let day = lDate.setDate(lastMonthNum);
lastMonthArr.unshift(this.getCurrentDate(day));
lastMonthNum--;
}
}
if (temaryDateArr[temaryDateArr.length - 1].day < 7) {
//下月日期补充列表
for (let i = 1; i <= nexMonthSurplus; i++) {
let day = nDate.setDate(i);
nextMonthArr.push(this.getCurrentDate(day));
}
}
// end
this.calendarData = [...lastMonthArr, ...temaryDateArr, ...nextMonthArr];
},
/**
* 获取当前时间戳的日期
*/
getCurrentDate(timeStamp) {
let nowDate = new Date(timeStamp);
let nowYear = nowDate.getFullYear();
let nowMonth = nowDate.getMonth() + 1;
let nowDay = nowDate.getDate();
let obj = {
disabled: nowYear != _year || nowMonth != _month ? true : false,
currentDate: `${nowYear}-${nowMonth}-${nowDay}`,
date: nowDay,
day: nowDate.getDay() == 0 ? 7 : nowDate.getDay(),
};
return obj;
},
/**
* 个位补零
*/
formatZero(num) {
if (String(num).length > 1) return num;
return `0${num}`;
},
/**
* 点击当前日期
*/
handleClickDate(e) {
let { currentDate } = e;
this.currentDate = currentDate;
},
/**
* 切换到上月
*/
handleLastMonth() {
if (_month == 1) {
//跨年
_year--;
_month = 12;
} else {
_month--;
}
this.getFullMonth();
},
/**
* 切换到下月
*/
handleNextMonth() {
if (_month == 12) {
//跨年
_year++;
_month = 1;
} else {
_month++;
}
this.getFullMonth();
},
},
};
</script>
<style lang='scss' scoped>
.calendar {
width: 100%;
padding: 30px;
&-header {
font-size: 16px;
.next-month {
font-size: 14px;
margin-left: 10px;
padding: 5px 10px;
border-radius: 4px;
}
}
&-main {
.week {
margin-bottom: 30px;
&-box {
flex: 1;
font-size: 18px;
// font-weight: 600;
text-align: center;
}
}
.calendar-wrapper {
.calendar-box {
width: calc(100% / 7);
height: 85px;
font-size: 14px;
&:hover {
cursor: pointer;
background-color: #f2f8fe;
}
}
}
}
.active {
cursor: pointer;
background-color: #f2f8fe;
}
.padding,
.padding-s,
.padding-xl {
box-sizing: border-box;
}
.padding {
padding: 10px;
}
.padding-s {
padding: 5px;
}
.padding-xl {
padding: 20px;
}
.flex {
display: flex;
}
.flex-wrap {
flex-wrap: wrap;
}
.justify-between {
justify-content: space-between;
}
.justify-around {
justify-content: space-around;
}
.justify-end {
justify-content: end;
}
.aligin-center {
align-items: center;
}
.shadow {
box-shadow: 0 2px 12px 0 rgba($color: #000000, $alpha: 0.2);
}
.line {
border: 1px solid #dcdfe6;
}
.line-bottom {
border-bottom: 1px solid #dcdfe6;
}
.line-left {
border-left: 1px solid #dcdfe6;
}
.line-right {
border-right: 1px solid #dcdfe6;
}
.line-top {
border-top: 1px solid #dcdfe6;
}
.round {
border-radius: 8px;
}
.disabled {
color: #c0c4cc;
}
}
</style>