vant里的组件没有提供上下月切换的效果,故自己仿造实现了一个
效果:
<template>
<div>
<div class="title-wrap">
<div @click="preMonth">
<img
src="../../assets/images/home/calendar/leftArrowSolid.png"
alt="上月"
/>
</div>
<div class="title" @click="show=true">{{ year }}年{{ month }}月</div>
<div @click="nextMonth">
<img
src="../../assets/images/home/calendar/rightArrowSolid.png"
alt="下月"
/>
</div>
</div>
<div class="weekdays">
<span class="weekday">日</span>
<span class="weekday">一</span>
<span class="weekday">二</span>
<span class="weekday">三</span>
<span class="weekday">四</span>
<span class="weekday">五</span>
<span class="weekday">六</span>
</div>
<div class="body">
<div class="month">
<div role="grid" class="days">
<div class="month-mark" style="">{{ Number(month) }}</div>
<div v-for="item in daysList" :key="item.day" :class="{day:true,active:item.active,today:item.today}"
:style="item.day===1 && {'margin-left': left + '%'}">
{{ item.day }}
</div>
</div>
</div>
</div>
<van-popup v-model="show" round position="bottom">
<van-picker
title="选择月份"
show-toolbar
:columns="columns"
@confirm="onConfirm"
@cancel="onCancel"
/>
</van-popup>
</div>
</template>
<script>
import computeWeek from "../../assets/js/helper/computeWeek";
import getDaysInMonth from "../../assets/js/helper/getDaysInMonth";
import { startYear, fullYear, fullMonth } from "../../assets/js/helper/yearMonth";
import {isRecordedDay} from '../../api/myCalendar';//该天是否有记账记录
import isToday from '../../assets/js/utils/isToday';
import Vue from 'vue';
import {Popup, Picker} from 'vant';
Vue.use(Popup);
Vue.use(Picker);
export default {
data() {
return {
year: 2021,
month: 1,
show:false
};
},
mounted() {
let date = new Date();
this.year = date.getFullYear();
this.month = fullMonth[date.getMonth()];
},
computed: {
left() {
let week = computeWeek(this.year, Number(this.month));
return ((week / 7) * 100).toFixed(4);
},
daysList(){
let days = getDaysInMonth(this.year, Number(this.month));
let list = [];
for (let i = 1; i <= days; i++) {
list.push({day:i,active:isRecordedDay(this.year,Number(this.month),i),today:isToday(this.year,Number(this.month),i)});
}
return list;
},
columns() {
return [
// 第一列
{
values: fullYear,
defaultIndex: this.year - startYear,
},
// 第二列
{
values: fullMonth,
defaultIndex: this.month - 1,
},
]
}
},
methods: {
nextMonth() {
let month = Number(this.month);
if (month + 1 <= 12) {
this.month = fullMonth[month];
} else {
this.month = fullMonth[month - 12];
this.year += 1;
}
},
preMonth() {
let month = Number(this.month);
if (month - 1 >= 1) {
this.month = fullMonth[month - 2];
} else {
this.month = fullMonth[month + 10];
this.year -= 1;
}
},
onConfirm(value, index) {
this.year = value[0];
this.month = value[1];
this.show = false;
},
onCancel() {
this.show = false;
},
},
};
</script>
<style scoped>
.title-wrap {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 0.2rem;
}
.title-wrap img {
width: 0.4rem;
height: 0.4rem;
}
.title {
height: 0.88rem;
font-weight: 500;
line-height: 0.88rem;
text-align: center;
font-size: 0.28rem;
}
.weekdays {
font-size: 0.32rem;
display: flex;
}
.weekdays .weekday {
flex: 1;
font-size: 12px;
line-height: 30px;
text-align: center;
border-bottom: 0.1rem solid #efefef;
}
.body {
font-size: 0.32rem;
-webkit-box-flex: 1;
flex: 1;
overflow: auto;
}
.days {
position: relative;
display: flex;
flex-wrap: wrap;
user-select: none;
}
.month-mark {
position: absolute;
top: 50%;
left: 50%;
z-index: 0;
color: rgba(242, 243, 245, 0.8);
font-size: 3.23rem;
transform: translate(-50%, -50%);
pointer-events: none;
}
.day {
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
text-align: center;
position: relative;
width: 14.285%;
height: 1.28rem;
font-size: 0.32rem;
position: relative;
}
.day.active{
background-image: url("../../assets/images/home/calendar/gou.png");
background-size: 50%;
background-repeat: no-repeat;
background-position: center;
}
.day.today{
background-color: rgba(0,1,0,0.08);
}
.day.today::after{
content: '今天';
font-size: 0.15rem;
color: red;
position:absolute;
right: 0;
top: 0.1rem;
}
.selected-day {
cursor: pointer;
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
text-align: center;
width: 1.08rem;
height: 1.08rem;
color: #fff;
border-radius: 4px;
background: rgb(0, 150, 136);
}
相关js文件
- computeWeek.js
/**
* 计算year年month月的1号是星期几(0,周日),(1,周一)...
* ->蔡勒(Zeller)公bai式
* @param {*} year
* @param {*} month
*/
function computeWeek(year, month, day = 1) {
if(month<3){
month += 12;
year -= 1;
}
const c = Math.floor(year / 100);
const y = year - c * 100;
let week = y + Math.floor(c / 4) - 2 * c + Math.floor( y / 4) + Math.floor(13 * (month + 1) / 5) + day - 1;
while (week < 0) {
week += 7;
}
week %= 7;
return week;
}
export default computeWeek;
2.getDaysInMonth.js
/**
* 给定年月判断有几天
* @param {*} year
* @param {*} month
*/
export default function getDaysInMonth(year,month){
return new Date(year, month, 0).getDate()
}
3.yearMonth.js
let startYear = 1900;
let endYear = 2100;
let fullYear = [];
let fullMonth = ['01','02','03','04','05','06','07','08','09','10','11','12'];
const fullWeek=["天","一","二","三","四","五","六"]
for(let i=startYear;i<=endYear;i++){
fullYear.push(i);
}
export {startYear, fullYear, fullMonth, fullWeek}
- isToday.js
export default function isToday(year,month,day){
const date = new Date();
return year==date.getFullYear() && month==date.getMonth()+1 && day==date.getDate()
}