前言:最近想练习一下JS的API,经过再三思考,自认为用原生JS写UI组件是一个好方法,理由有:
a. 熟悉大量原生API,像什么字符串,数组,DOM操作是肯定跑不了的
b. 可以锻炼逻辑思维能力。插件的需要基本一样,要实现什么功能不用自己太多考虑可以把主要精力放在功能实现上面,即代码层面的分析和解决问题能力
c. 可以加强自己的信心。写组件就是对自己前端能力的综合锻炼,涉及的知识面会很广。
一: 日历组件需求(要实现的功能)
b. 某年某月的日期能正常显示(某月有多少天,某一天是星期几)
c. 上一月,下一月切换功能
d. 假日提示功能,能自定义节假日
最近效果如下图:
二:问题拆分及解决过程
问题a: 界面构建问题
解决办法:通过分析windows任务栏日历,发现其界面就是一个 7*6 的固定的格子块。像这样较多数据展示当然用table了。然后thead里面的th来展示星期,caption来展示当前年月。考虑到每天有选中,hover等效果所以在td里面多使用了a标签(根据经验,是不推荐直接使用td裸标签,因为td的display属性是table-cell,其样式控制不够好)
问题b: 参数设计
解决办法:因为以前写过一些基于jQuery的插件,所以参数上也使用了jQuery插件常用的默认加自定义的方式.因为没有使用JS库,所以在Canlendar上面挂了一些工具方法.
问题c:如果正确显示每一个月的天数,即某月有多少天,某一天是星期几.
解决办法:通过分析发现:
1. 1个月最多有31天,而我们有7*6=42个格子(最多能显示42天),所以只需要找到一个合适的开始位置"把把每月天数(从1连续的超过31的整数)放入格式即可.
2. 上面所提到的"合适的开始位置"即把当前月的1号与星期给对应上
3. 做一些恰当优化,因为研究windows日历会发现,如果某月1号是星期天,那么"合适的开始位置"其实是第二行的第一个位置,而不是第一行的第一个位置
通过上面分析,我们发现多出了两个要解决的问题:
1. 某年某月有多少天;
2. 某月的1号是星期几
问题解决代码如下:
问题d: 如果实现自定义节日
解决办法: 对Canlendar类(型)增一个域:festival,这个域的产生会取默认与自定义节日的一个并集,是一个对象数组.在每渲染日历后,会根据此数组对td里面的a标签加一个date-festival的自定义属性,然后使用a::after伪元素来显示此属性
问题e:其它
1. 每个Canlendar对象有一个_canlendar属性,包含了四个属性.始终根据此对象去计算并渲染日历
3. 在放多API设计上采用了jQuery的思想,把setter,getter合到一个API上面,只有一个参数是getter,两个参数是setter.如前面提供的month()方法