3
ui参考primeNG: http://primefaces.org/primeng...
ts开发环境:https://github.com/lycHub/ts-...
目录

简介

日历插件有很多,形态各异,但不管什么插件,只要掌握其基本实现原理,就能写出通用性很强的轮子。
本节日历demo源码
已实现的功能:

  • 不可选日期
  • 默认选中日期
  • 多面板
  • 范围选择
  • 自定义事件

基本思路

可以先把一个日历面板的静态布局写好,包括选中,非当月日期,禁止点击等样式:

clipboard.png

写好静态部分后,可以先用假数据填充天数部分(就是所有的td),这些td我是用一个类似矩阵(6行7列)的二维数组,用for循环生成的,
假的矩阵数组可以这样生成:

const dateArr = [];
for (let a = 0; a < 6; a++) {
  dateArr.push(Array(7).fill(a));
}
console.log(dateArr);

clipboard.png

生成了一个假数据的面板后,可以思考怎么换成真数据,我的思路是:
取得每个月(比如截图的2019.6)第一行第一列的日期,生成6 * 7个td
在生成的时候判断每个td是否默认被选中,时候禁用,是否在当月(2019.6),是否当天,然后添加不同的class样式
也就是DatePicker.ts的这段:

clipboard.png

这里面引入了日期库——date-fns,官方文档要翻墙,可以看这个翻译的Docs

至于多面板,我是用monthNum控制的,默认为1

clipboard.png

dateArrs组装成功后,就可以用dom操作渲染面板了,就是DatePicker.ts里的initDatePicker方法

切换月份

切换月份比较简单,只要处理好边界,在重新渲染一遍数据即可:

clipboard.png

点击日期

首先禁用的不可点,然后是不是范围选择(options.range是否为true),这个要分开写逻辑
不管什么选择,我这里先把所有td的activedclass去除了(这个去除时机并非最好)
如果不是范围选择,只需给点击的td加上actived的样式,赋值给_value,发射onChange事件

clipboard.png

如果是范围选择:
要区分点击次数,处理两次点击目标的时间先后顺序

clipboard.png

配置项和自定义事件

经常写插件的也许不用说也知道,这两个特性是插件必备的。

配置项和自定义事件的设计都是参照黄大仙Bscroll的,
配置项有默认的一套,用户传入后进行合并,也就是我源码中Options.ts的逻辑
自定义事件的逻辑在EventEmitter.ts中,我只实现了点击td的change事件,用户可以在配置项中监听,也可以调用实例上的on方法

clipboard.png

源码我已经写了足够详细的注释,可以clone下拉直接运行,我的实现思路可能不是最好的,欢迎网友们晒出自己的demo和建议咯.


会js的诸葛村夫
282 声望617 粉丝

主angular,兼ts|webpack|rxjs|vue,擅长造轮子