今天对vant组件中的van-calendar通过插槽方式,丰富功能。
主要是通过《》来控制年份选择,<>来控制月份选择。这样就能保证一直是以日期为最终点。
可通过《》转换年月。
1.view层的代码
主要采用插槽对日期选择器实现修改、
<van-calendar
v-model="showCalendarDay"
@confirm="onConfirmDay"
:min-date="minDayDate"
:max-date="maxDayDate"
:show-subtitle="false"
ref="currentDate"
:formatter="formatter"
:show-confirm="false"
:show-mark="false"
>
<template v-slot:title>
<div class="title-top">
<div class="back" @click="backDate()">回到当月</div>
<div>xxxxxxx</div>
</div>
<div class="title-bottom">
<div class="bottom-left">
<img
src="@/assets/inspection-report/arrowdoubleleft.png"
class="calendar"
alt=""
@click="scrollToDate(-1, 'year')"
/>
<img
src="@/assets/inspection-report/arrow.png"
class="calendar"
alt=""
@click="scrollToDate(-1, 'month')"
/>
</div>
<span class="tit">{{ textDay }}</span>
<div class="bottom-right">
<img
src="@/assets/inspection-report/arrowright.png"
class="calendar"
alt=""
@click="scrollToDate(1, 'month')"
/>
<img
src="@/assets/inspection-report/arrowdoubleright.png"
class="calendar"
alt=""
@click="scrollToDate(1, 'year')"
/>
</div>
</div>
</template>
</van-calendar>
2.JavaScript部分
我感觉最陌生的部分就在于formatter这一部分,在实现的时候感觉没有思路。
思路是逐一匹配,当匹配到的时候,就赋对应的样式class类。
整体的流程就是
在点击触发日期选择器打开时,调用接口获取数据,转换数据格式,在本代码中,日期部分我是采用了2024-06-06这种格式,当日期匹配时,就赋值样式class。这样实现界面数据渲染。
通过scrollToDate方法实现年月的转变,并获取修改后的年月。
formatter(day) {
const formattedDate =
day.date.getFullYear() +
"-" +
("0" + (day.date.getMonth() + 1)).slice(-2) +
"-" +
("0" + day.date.getDate()).slice(-2);
this.dailyList = this.abnomalDateList;
const fakeItem = this.dailyList.find(
(item) => item.attendDate == formattedDate
);
if (fakeItem) {
// day.topInfo = fakeItem.abnomaleName;
if (fakeItem.abnomaleName === "请假") {
day.className = "is";
} else {
day.className = "no";
}
}
return day;
},
backDate() {
let newDate = new Date();
this.textDay = formatDate(newDate, "YYYY年MM月");
this.minDayDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
this.maxDayDate = new Date(
newDate.getFullYear(),
newDate.getMonth() + 1,
0
);
},
scrollToDate(type, dateType) {
let newDate = this.data;
if (dateType === "year") {
newDate.setFullYear(newDate.getFullYear() + type);
} else {
newDate.setMonth(newDate.getMonth() + type);
}
this.textDay = formatDate(newDate, "YYYY年MM月");
this.minDayDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
this.maxDayDate = new Date(
newDate.getFullYear(),
newDate.getMonth() + 1,
0
);
console.log(
77788,
newDate,
this.textDay,
this.minDayDate,
this.maxDayDate
);
},
3.样式部分的代码
有一点:日期选择器存在默认选中的情况,所以在深度修改的时候,需要格外注意。
::v-deep .van-calendar__header-title {
height: 84px !important;
}
::v-deep .van-calendar__month-title {
display: none !important;
}
::v-deep .van-calendar__selected-day {
border-radius: 50% !important;
}
::v-deep .van-calendar__day {
height: 54px !important;
background-color: #f0f4fd !important;
color: #6393e8 !important;
border-radius: 50% !important;
border: 3px solid #fff !important;
box-sizing: border-box !important;
}
::v-deep .van-calendar__days {
margin-top: 8px !important;
}
::v-deep .is .van-calendar__selected-day {
// background-color: #d5dff6 !important;
background-color: #f0f4fd !important;
color: #6393e8 !important;
}
::v-deep .no .van-calendar__selected-day {
// background-color: #ffc5c5 !important;
background-color: #feebeb !important;
color: #f76060 !important;
}
::v-deep .no {
background-color: #feebeb !important;
color: #f76060 !important;
border-radius: 50% !important;
}
::v-deep .is {
background-color: #f0f4fd !important;
color: #6393e8 !important;
border-radius: 50% !important;
}
::v-deep.van-calendar__popup.van-popup--bottom,
.van-calendar__popup.van-popup--top {
height: 68% !important;
}
.title-top {
display: flex;
align-items: center;
justify-content: center;
position: relative;
.back {
position: absolute;
left: 15px;
height: 30px;
background-color: #739eea14;
color: #6393e8;
padding: 0 5px;
display: flex;
align-items: center;
border-radius: 5px;
cursor: pointer;
}
}
.day-cell {
background-color: #6393e8;
}
.title-bottom {
display: flex;
justify-content: space-between;
margin: 0 15px;
}
.calendar {
width: 15px;
height: 15px;
margin: 0 5px;
}