这是苹果上的日历截图,从上面的内容来看,有公历,农历,24节气和节日。
平时在使用实体日历的时候,的确是有些印刷的日历会从星期一开始,而使用电子产品的时候,大多数都是从星期天开始的。
不过这个问题还是比较好解决的,首先看下日历的头部。
从截图上看出,不管是那天开始,整体的顺序不变,而且有没有发现,这个情况和无缝滚动的组件很像,内容滚出视图外,自动补充到末尾,就像一个圆环。
那我们基于无缝滚动的原理,就很容易获得一周7天的数字。
既然原理分析出了,那我们就可以很容易的写出代码:
那我们再进一步,转化成日历的头部,顺便支持国际化
//简体中文constzh={//完整名称weekdays:['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],//短名称weekdaysShort:['周日','周一','周二','周三','周四','周五','周六'],//缩写weekdaysAbbr:['日','一','二','三','四','五','六']}//英文consten={//完整名称weekdays:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],//短名称weekdaysShort:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],//缩写weekdaysAbbr:['Sun','Mon','Tue','Wed','Thu','Fri','Sat']}/***获取一星期的名称列表**@param{Number[]}weekdays一周7天的数字**@param{Object[]}*/functiongetWeekHead(weekdays,locale){returnweekdays.map(day=>({name:locale.weekdays[day],short:locale.weekdaysShort[day],abbr:locale.weekdaysAbbr[day],day:day}))}打开Chromedevtools执行下,基本额可以达到我们的预期
这个很正常,周的开始都不确定,何况是月天数不固定。
我们从上面的图也可以看出来,月结束和开始都不固定,那我们该如何处理?
可能又点绕,我们用图片说话:
那我们知道如何计算之后,就可以开始准备数据了。
首先我们需要知道,1号是星期几,这个在js中,直接通过Date#getDay()就可以知道是星期几
但因为前面说过了,周的开始是不固定的,所以我们计算的时候,还需要前面的函数辅助才能知道应该减少几天。
到这里可能会有人疑惑,每个月份的天数都不固定,而且还有润月的问题;就算我们知道要减少几天,计算上一个月的最后一天也是一个麻烦事情,这个应该如何解决呢?
其实这个也非常简单,在js中Date对象已经帮帮我们处理好了。
到这里我们所有的条件都已经准备完毕了,剩下的就交给循环了。
试试周一开始
目前看来,日期和星期都按我们预想的那样执行了,剩下的就是渲染问题。
其实当我们数据准备好的那一刻,基本上这个日历也就差不多完成了,剩下的是往上面堆功能。
我们只要数据处理好,那我们就可以使用任何框架,甚至在任何支持Date对象的js环境中运行了,比如在nodejs上运行。
打印2021-01月,以周一开始的日历
农历和节假日可以通过数据的方式手动维护,不过节气可以维护到组件中。
写一个日历,也是一件比较麻烦的事情,幸好大部分前端用到的日历都不要求农历,24节气和节日,不然头发都要多掉好几根。