携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
前言
上一段时间需要做一个包含周报功能的,大致效果如下图所示:
一开始的打算是寻找一个开源插件的,但是经过一段时间的调研发现,没有十分契合的插件,要么是满足功能,但是ui调整起来比较费力;要么是ui很契合,但是功能与期望有差距。经过一段时间的挣扎与评估,最终决定自己手撕。
工具
插件库:dayjs 开发工具:vscode
之所以选用dayjs,完全是因为dayjs封装的很好,处理了日期的很多兼容性问题,而且体积不是很大。
核心逻辑
1. 计算当前月的第一周
获取当前月的第一天相对来说很简单,这里简单的介绍两种方式:
- 获取当前时间的年+月,然后拼接上日期01即可;
const day = dayjs();
const year = day.year().toString();
const month = (day.month() + 1).toString();
// year+month+01
- 借用dayjs提供的startOf方法
dayjs().startOf('month')
获取了每个月的第一天了,但是并不意味着我们找到了每个月的第一个周。试想一下,如果这个月的第一天是星期二到星期日,这就意味着这个月的前几天(星期日之前)是上一个月的最后一个周;如果这个月的第一天是星期一,这就意味着这个月的第一天是这个月的第一个周的开始时间。
也就是说我们要判断一下,每个月的第一天是星期几,如果是星期一那么这个月的第一周的起始时间就是1号,否则那么下一个星期一才是这个这个月的第一周的开始时间。
我这里也是直接借用了dayjs来实现的:
let day = dayjs(date).startOf('month').day(1);
if (day.date() > 7) {
day = day.add(1, 'week');
}
特殊说明一下:dayjs获取的day(1)是当前时间所在周的星期一的日期,所以说如果大于7,说明是上个月的最后一个周,那么只需要在这个基础上加上7天,就是这个月的第一个周的星期一的日期了。
2. 生成日期列表
既然有了当前月的第一个月的开始时间,那么结束时间也就可以拿到了,只需要加6就可以了
day.add(6, 'day');
既然有了第一个周,那么剩下的周只需要进行循环即可拿到了,但是循环的终止机制有啥怎么触发呢?如何确认时间是否是进入了下一个月了呢?
其实说起来很简单,只需要判断时间再次小于等于7即可,理解了这个之后,剩下的就很简单了,这里我就直接亮一下我的代码了:
const weekList = [];
let day = getFirstMondayOfMonth(date);
do {
const { start, end } = getIntervalDateOfWeek(day);
weekList.push({ start, end });
day = day.add(1, 'week');
} while (day.date() > 7);
尾语
到这里一个周日历插件的逻辑就基本实现了,剩下的只需要进行一下简单的切换和ui的调整即可了。希望小编说的这个对大家的日常开发过程有所帮助,欢迎大家在下方进行留言交流。