课程前言:
慕课网 -- DatePicker组件开发
课程准备:
HTML、CSS、JavaScript基础、浏览器事件
静态结构的编写、日历数据、数据渲染、事件处理
静态结构的编写:
header分为三部分,向上翻页的button,向下翻页的button,还有就是中间的当前月份显示。
body部分是一个表格的呈现,分为两个部分,表头是周一到周日的呈现,表格内容是每一个单元格就是一个日期。
组件的样式命名,会比较长(复杂),开发的是一个组件,那这个组件就会被应用到各个页面上,如果过于简单,就会跟页面上的元素class命名冲突,带来不必要的麻烦。因此,组件的样式命名就比较独特,可以长一点。
a元素实现按钮,是因a自带手形图标。一般来说,可点击的按钮都需要一个提示。
静态样式的编写:
box-shadow:给盒子一个悬浮于页面的效果,box-shadow:2px2px8px2pxrgba(128,128,128,.3);
级联选择器:避免与外界发生冲突。background-color:#f0f0f0; 它是区别于白色的背景色。为了使字体符号更像图标,会设置字体的样式,font-family:Serif; a标签有href属性时,就会有下划线。
border-collapse:collapse;是说,table中,相邻的两个表格线会折叠一条。选中状态下 shift+cmd+上下箭头即上下移动;
日期对象:
new Date (year,month-1,date) 其中,月份需要-1.越界自动 进退位,还有 getFullYear() ,getMonth() , getDate() .
getYear() 是说,距离 1900 年多少年,比如2017 getYear() 后就是 117年;但getFullYear() 就是 2017年了。
getDay() 当前日期在一周中是周几。
当月第一天 new Date(year, month-1, 1) 日期指定1,月份是从0开始的,所以要-1,year也都是正常的 2017 呀等。
当月最后一天 new Date(year, month, 0) 日期指定 0,月份是month,没有减1,其实就是下个月咯,下个月的第0天,表示上一个月的最后一天。(因月份的最后一天,不一定都是31,因此,我们用 下一个月的 0 来表示 这个月的最后一天。这是利用了日期的自动进退位。)
星期一 到 星期天,[1,2,3,4,5,6,0] ,这个数组是 getDay() 的返回值。一个星期的开始,是从周天开始的,也就是0开始的,你知道为什么吗?✌️
获取日历数据:
利用JS获取日历的核心数据
日期数据的渲染:
有时聊渲染,其实就是一个html。
整个过程细心就好了,其实就是比较繁琐。 < 小于号,>;大于号,因普通的跟看起来有点不同,那就调整一下字体就好了。span中间是当前月份的显示,都是从 monthData中拿到,前期数据的准备非常重要。
输入框的展开与收起:
优化着手点有两方面:
1.当用户点击输入框的时候,日期组件才可以显示,不能一打开页面,它就在,太不友好了;
2.目前的日期组件的主题结构 wrapper header body是占据文档流的,如果页面里还有其他的内容,会因日期的出行,下移的,因此将其样式改为绝对定位。
元素的显示与隐藏:方式很多样;最通用是通过class来控制,默认是隐藏,除非多了一个 block 的样式,后者覆盖前者,wrapper就才显示出来。 .classList.remove 与 .classList.add 的 使用。 isOpen 布尔值 来记录当前是关闭状态还是展开状态。
日期组件的绝对定位:目标是希望它出现在输入框的下方,所以就要先找到输入框目前在页面的哪个位置呢: var left = $input.offsetLeft; var top = $input.offsetTop; var height = $input.offsetHeight; $wrapper.style.top = top + height + 9 +'px'; $wrapper.style.left = left + 'px';(切记,这里用style给宽高的时候,加上 px 呢。)
月份切换:
本节课的出发点:左右按钮切换时,进入上一月,或者下一月。初始化的时候,给按钮绑定事件。但这种情况,是在组件初始化的时候才有效,事件只绑定了一次;但页面渲染之后,内容里是根据按钮再重新渲染的,我们的按钮也是感觉HTML字符串再重新渲染的,因此就会有按钮不断的销毁与重建。
datepicker.render('prev') datepicker.render('next') 是谁:
日期点击选中:
data-*是一个比较新的API,老的浏览器不能使用。*是要替换成自己命名的字符。为一个标签添加一个此属性后,js取值的时候是: target.dataset.d; target:添加此属性的标签对象 dataset:固定写法 d:添加的属性名的后半部分,即data-*中“-”后自己命名的字符。
日期组件的使用:
调用方法由繁入简,最后只有 .init 里,传一个样式。
而一个日期组件的出现,就依靠这个输入框了。而这个输入框的样式,因为不属于组件,因此就写在页面里咯~
课程总结(组件开发流程):
使用HTML合理规划组件结构;
为组件编写美观的样式;
如何使用JavaScript获取组件所需数据;
将数据与HTML结构结合;
用户事件处理;
整个日期组件的出现,就是从 init 开始,然后 init 在绑定相关的点击操作之前,首先调用 render 来渲染这个的日期组件;然后,render里,写的是 日期组件中的数据,还有左右两边的上下按钮;render里的数据,则是从 buildUi 里来的,包括样式,都是一致的。
小技能:
var$input =document.querySelector('input');
$wrapper.classList.add('ui-datepicker-wrapper-show');
$wrapper.classList.remove('ui-datepicker-wrapper-show');
if(!$target.classList.contains('ui-datepicker-btn'))return;
if($target.tagName.toLowerCase() !='td')return;
不写备注了,试试看,能否想起来啦。
后续可完善的功能:
如何在移动端使用日期组件;
当页面比较复杂的时候,如何处理,弹出框的位子;
如何标记上一个月与下一个月的日期,使它们拥有不同的样式;
某一些日期可点,某一些日期不可点。
写在最后,写给自己:
整个组件开发的核心,是日期数据的获取,那老师都已经给出思路了,我是否愿意写一写可完善的功能;如果我觉得JS不那么的熟悉,是否可以使用React重新开发该框架呢?如果想要重写,大概要多久呢?