
日历插件并不少见,但多数都是大而全,直接使用插件的话往往会使项目变得臃肿,而且想做一些定制化的修改,成本反而会更高。
最近为了练手Taro框架,做了一个日历微信端小程序,大海日历,刚好用到日历输出。项目开始时也想偷个懒直接找网上插件来使用,但找来找去,大多数插件都做的大而全,觉得比较臃肿,而且定制成本都偏高,当然也不排除是我自己没找到的原因哈。于是,综合分析一下,还是自己动手吧。
需求分析
首先描述一下需求:
输出本月日期,按照星期分成行;
空余位置用其他月份日期补全;
某些月份日期占6行,某些月份日期占5行,为了切换月份时保证视觉效果,我们要固定所有月份都按6行铺排;
西方习惯周日为每周第一天,中国更习惯周一为每周第一天,所以要支持此设置。
我们从以上需求可分析出:
首先需要计算本月第一天的星期;
当前可视日期数量为6 * 7 = 42;
支持传入”每周第一天是否是周一”参数;
输出为7 * 6结构二位数组。
网上很多实现,是通过月份天数、本月第一天的星期,来计算本月实际占几行,进而来判断是否需要补充一行其他月份日期。我们这里取个巧,不进行此判断,不管需不需要,我们都地毯式的循环输出42天,减少很多计算量。
另外还有一个可取巧的点,Date类支持设置日期为任意整数,并且程序会自动纠正成对应日期,比如:

注意:
设置月份时,和通过getMonth()获取月份时、通过getDay()获取星期时,使用的都是编程习惯的索引值,而非自然值,也就是计数从0开始;
月份范围是[0-11];星期范围是[0-6],0代表周日,也就是默认星期是以周日开始的;
而通过getDate()获取日期时,则使用的是自然日。
思路

日历第一天传入的date值
通过上图,得出,当本月第一天在周一到周日变化时,日历第一行第一天的日期取值范围为[1, 0, -1, -2, -3, -4, -5],我们利用本月月第一天的星期索引,即可算出具体日期:
取得本月第一天的星期索引,取值范围为[0, 1, 2, 3, 4, 5, 6];
当设置每周第一天为周日时,可通过1 - new Date().getDay()计算得出第一行第一天的具体日期;
当设置每周第一天为周一时,本月第一天为周一到周六日期可通过2 - new Date().getDay()计算得出,为周日时则设定为-5;
循环输出所有日期,我们可以设置两层循环,第一层循环用来设定当前日历的1-6周,第二层则用来设定每周的具体日期。
方法源码
具体方法实现如下:

日历效果,可以微信搜索大海日历小程序来体验。
其实日历核心部分也就短短十几行代码,相比臃肿的插件,瞬间感觉清爽不少,在做一些定制化需求时,也灵活多了。
本文永久链接: https://www.mulianju.com/javascript-calendar/