日历的js实现
根据指定的日期生成所在月份的日历数据,在前端展示上可能需要有上个月、下个月数据的填充。
- 填补上个月的日历数据 例如选取的一月份日历数据,该月份的第一天为周六,也就需要在周日到周五之间填补上个月的数据。 获取本月的第一天属于星期几:
const first = new Date(date).setDate(1);
let day = new Date(first).getDay();
first对应的值为时间戳的形式,为number类型。 day对应了本月第一天是星期几,星期对应数值为0~6,表示星期天到星期六。
填补上个月空缺值:
while(day > 0) {
// TODO 构造单个的日期项,加入总的日期列表
// Example
const dayItem = {};
dayList.push(dayItem);
day--;
}
- 填充本月的数据 由于每个月份的天数不一致,28~31天不等,所以选取最大值31天进行循环遍历。使用setDate来改变天数,若数据越界会自动改变设置日期所属的月份。
const cur = new Date(date);
const dd = new Date(date);
for(let i = 1; i <= 31; i++) {
dd.setDate(i);
if (dd.getMonth() !== cur.getMonth()) {
break;
}
dayList.push({
daytime: new Date(dd).getTime(),
// TODO 自行定义日期项所需要的参数
});
}
dd的值会随着setDate而改变,需要保留初始的日期数据。
- 填充下个月的数据
// 获取本月的最后一天,也可以用其他方式获取
const last = new Date(dayList[dayList.length -1].daytime);
for(let i = 0; i < 6 - last.getDay(); i++) {
// TODO 构造单个的日期项,加入总的日期列表
// Example
const dayItem = {};
dayList.push(dayItem);
}
完整代码:
日历逻辑数据同时配合日历组件样式使用,可以更具需要自行定义style中的参数。在数据构造中,非本月的数据都是用了值0来填充,可以根据实际需要设置该值。
/* 构造指定日期对应月份的日历数据 */
function constructMonthData(date: Date, isPure = true) {
const dd = new Date(date);
// 获取当前日期
const now = new Date(dd);
// 月份数据列表
const dayList: DayItem[] = [];
// 本月的第一天
const firstDate = new Date(dd).setDate(1);
// 本月第一天对应的星期
let getDay = new Date(firstDate).getDay();
// 填补当前日历上个月的空缺项
while (getDay > 0) {
const dayItem = {
daytime: 0,
isCurrentMonth: false,
style: {},
};
dayList.push(dayItem);
getDay--;
}
// 填补本月数据
for (let i = 1; i <= 31; i++) {
dd.setDate(i);
if (dd.getMonth() !== now.getMonth()) {
break;
}
dayList.push({
daytime: new Date(dd).getTime(),
isCurrentMonth: true,
style: {},
});
}
// 填充下个月的空缺项
const lastDay = new Date(dayList[dayList.length - 1].daytime);
for (let i = 0; i < 6 - lastDay.getDay(); i++) {
const dayItem = {
daytime: 0,
isCurrentMonth: false,
style: {},
};
dayList.push(dayItem);
}
// 返回本月的数据
if (isPure) {
return dayList.filter((day) => day.isCurrentMonth);
}
return dayList;
}
补充:使用真实日期值填充上下个月的占位数据
填充上个月的数据:
let getDay = new Date(firstDate).getDay();
while (getDay > 0) {
const dayItem = {
daytime: new Date(firstDate).setDate(0 - getDay + 1),
isCurrentMonth: false,
style: {},
};
dayList.push(dayItem);
getDay--;
}
Date.prototype.setDate(0)
会被设置为上个月的最后一天,以此类推填补上个月和下个月的日期;
填充下个月的数据:
const lastDay = new Date(dayList[dayList.length - 1].daytime);
for (let i = 0; i < 6 - lastDay.getDay(); i++) {
const dayItem = {
daytime: new Date(lastDate).setDate(lastDate.getDate() + i + 1),
isCurrentMonth: false,
style: {},
};
dayList.push(dayItem);
}