这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
如下图要实现如下的日历,可以切换月份,默认显示当前月,有事件的日期下面有一个小点,今天之前的日期不可选,小点是灰色的,今天之后的日期可以选择。
原本想直接用vant的van-calendar的,但是完全不符合需要,无奈只能自己动手了,代码比较冗余,自己记录一下,温故而知新!
1.月份日历渲染
- 父组件的wxml
<van-popup show="{{ show }}" round position="bottom" custom-style="height: 55%" bind:close="onClose" closeable>
<the-calendar bindonCalendarClose="onCalendarClose"></the-calendar>
</van-popup>
复制代码
- 日历组件的wxml
<view class="calendar-container">
<view class="top-title">
<text class="fs16 black">测试时间</text>
</view>
<view class="choose-month">
<view class="month-left">
<view class="left-par">
<text class="iconfont iconxiangyou" bindtap="chooseMonth" data-state="-1"></text>
</view>
<text class="title">{{year}}年{{month}}月</text>
<view class="right-par">
<text class="iconfont icongengduo" bindtap="chooseMonth" data-state="1"></text>
</view>
</view>
</view>
<view class="days-area">
<view class="day week black-65 fs12" wx:for="{{weeks}}" wx:key="index">{{item}}</view>
<view wx:for="{{days}}" wx:key="index" wx:for-item="day"
class="day day-time fs12 {{day.chooseDay?'choose-day' : ''}} {{day.className}} {{day.event?'day-event':''}}"
bindtap="chooseThisDay" data-year="{{day.year}}" data-month="{{day.month}}"
data-gregorian="{{day.gregorian}}" data-className="{{day.className}}">{{day.title}}</view>
</view>
</view>
复制代码
2.日历事件渲染
// 获取当前月份所有日期
getDays() {
this.data.days = [];
const day = new Date();
day.setFullYear(this.data.year, this.data.month - 1, 1); // 获取当月第一天(月份减1)
const month = new Date();
month.setFullYear(this.data.year, this.data.month, 0); // 获取当月最后一天
const prevMonth = new Date();
prevMonth.setFullYear(this.data.year, this.data.month - 1, 0); // 获取上月
let prevDay = prevMonth.getDate(); // 上月的日期
let nextMonth = new Date();
nextMonth = new Date(this.data.year, this.data.month, 0); // 下月的日期
let nextDay = nextMonth.getDay(); // 最后一天星期几
for (let i = day.getDay() + 1; i > 1; i--) { // 当月第一天距离所在周周一(+1周日)的空白占位
let prevM = this.data.month - 1,
prevYear = this.data.year;
if (prevM < 1) {
prevM = 12;
prevYear = prevYear - 1
}
this.data.days.unshift({
year: prevYear,
month: prevM,
title: prevDay,
gregorian: prevDay,
className: 'grey'
})
prevDay--;
}
for (let i = 1; i <= month.getDate(); i++) { // 获取当月天数填充日历
let title = i;
if (this.data.year === this.data.yearNow && this.data.month === this.data.monthNow && this.data.todayNow === i) {
title = '今';
} ;
this.data.days.push({
year: this.data.year,
month: this.data.month,
title: title,
gregorian: i,
className: 'grey'
})
}
let j = 0,
nextM = this.data.month + 1,
nextY = this.data.year;
if (nextM > 12) {
nextM = 1;
nextY = nextY + 1;
}
for (let i = nextDay + 1; i < 7; i++) { // 当月最后一天距离所在周周六的空白占位
j++;
this.data.days.push({
year: nextY,
month: nextM,
title: j,
gregorian: j,
className: 'grey'
})
nextDay++;
}
// 日期的选中效果
this.data.days.forEach((itemD) => {
if (this.data.chooseDate.year === itemD.year && this.data.chooseDate.month === itemD.month && this.data.chooseDate.gregorian === itemD.gregorian) {
itemD.chooseDay = true;
}
})
this.setData({
days: this.data.days
})
},
// 改变年份
chooseYears(state) {
this.setData({
year: this.data.year += state
})
this.getDays();
this.getEventsList('change-month'); // 获取事件
},
// 改变月份
chooseMonth(event) {
let state = event.currentTarget.dataset.state;
this.setData({
month: this.data.month += Number(state)
})
// 月份 年份变化
if (this.data.month < 1) {
this.setData({
month: 12
})
this.chooseYears(-1)
} else if (this.data.month > 12) {
this.setData({
month: 1
})
this.chooseYears(1);
} else {
this.getDays();
}
this.getEventsList('change-month'); //月事件
},
复制代码
3.以今天为分界,渲染事件
// 获取月事件
getEventsList(flag) {
let obj = {
starDate: this.data.starDate,
endDate: this.data.endDate,
resId: this.data.resId,
}
$post(getCalendarBoardByResId, obj).then(res => {
this.getEventData(res);
})
},
// 处理事件数据结构
getEventData(newData) {
let nowDate = new Date().getTime() - 8.64e7;
if (newData.length > 0) {
newData.forEach((itemN) => {
this.data.days.forEach((itemD) => {
if (itemN.year === itemD.year &&
itemN.month === itemD.month &&
itemN.day === itemD.gregorian
) {
itemD.event = true;
let thisDate = new Date(itemD.year + '-' + this.addZero(itemD.month) + '-' + this.addZero(itemD.gregorian)).getTime();
if (thisDate >= nowDate) { // 今天以后的日期可点击
itemD.className = '';
}
}
})
})
} else {
this.data.days.forEach((itemD) => {
itemD.event = false;
})
}
this.setData({
days: this.data.days
})
},
复制代码
4.日期的点击事件
// 选择某天
chooseThisDay(e) {
// 点击今天之前的日期 不可点击
if (e.currentTarget && e.currentTarget.dataset && e.currentTarget.dataset.classname == 'grey') {
return;
}
let day = e.currentTarget.dataset;
let flag = 0;
this.data.days.forEach((itemD) => {
itemD.chooseDay = false;
if (day.year === itemD.year && day.month === itemD.month && day.gregorian === itemD.gregorian) {
if (itemD.className === 'grey') {
flag++;
} else {
itemD.chooseDay = true; // 选中
}
}
if (this.data.yearNow === itemD.year && this.data.monthNow === itemD.month && this.data.todayNow === itemD.gregorian) {
itemD.isToday = true; // 今天
}
})
if (flag > 0) {
return false;
}
this.setData({
today: day.gregorian,
chooseDate: {
year: day.year,
month: day.month,
gregorian: day.gregorian
},
days: this.data.days
})
// 父级回调
this.triggerEvent('onCalendarClose', {
year: day.year,
month: day.month,
gregorian: day.gregorian
});
},
复制代码
好了,以上就是日历组件的全部代码啦。感谢观看!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END