一个简单的扁平化组件——datePicker日期选择器
效果图
使用方法
-
引入datePicker.css 文件
-
引入 date.js文件、datePicker.js 文件
在html里创建一个input,在js里调用datePicker.init(),参数为你的input
主要过程
- 使用HTML和CSS编写组件静态UI
- 使用原生javascript完成日历数据获取
- 使用原生javascript实现静态UI和动态数据结合,完成日历数据渲染
- 事件绑定处理
使用HTML和CSS编写组件的静态UI
承载日历数据的主要结构为table 确定了配色和扁平化的效果
color:#ccc; //文字颜色
color: #1abc9c; //主题色
background: #E63946; //前景色
box-shadow: 2px 2px 8px 2px rgba(128,128,128,.3);//阴影效果
使用原生JavaScript完成日历数据获取 (date.js部分)
生成7*6的日期数据
Date()对象有自动进退位的机制,例如2018.4.0表示2018年3月的最后一天
特殊处理上一个月、下一个月的数据
for (var i = 0;i<6*7;i++){
var date = i+1-preMonthDayCount;
var showDate = date;
var thisMonth = month;
if(date<= 0){
thisMonth = month-1;
showDate = lastDateofLastMonth + date;
}else if(date>lastData){
thisMonth = month+1;
showDate = showDate - lastData;
}
if(thisMonth === 13) thisMonth = 1;
if(thisMonth === 0)thisMonth = 12;
将结果对象push到数组
date 为全部未处理的数据,包含上一个月的末尾(负数),本月的全部,下月的开始 (大于本月最后一天的整数)
month 为当前月份
showDate 为处理完毕正常显示的数据
ret.push({
date:date,
month:thisMonth,
showDate:showDate
});
讲包含年份,月份,储存有7*6个日期的数组作为对象返回
return {
year:year,
month:month,
days:ret
};
使用原生javascript实现静态UI和动态数据结合,完成日历数据渲染
将原来的静态模板界面改造为脚本动态生成
特殊处理上一个月月末、当前天、下一个月月初的日期显示
拼接成字符串并返回
datepicker.buildUI = function(year ,month){
monthDate = datepicker.getMonthDate(year,month);
var html = '<div class="ui-datePicker-header">'+
'<a href="#" class="ui-datePicker-btn ui-datePicker-prev-btn"><</a>'+
'<a href="#" class="ui-datePicker-btn ui-datePicker-next-btn">></a>'+
'<span class="ui-datePicker-curr-month">'+ monthDate.year+'-'+monthDate.month + '</span>'+
'</div>'+
'<div class="ui-datePicker-body">'+
'<table >'+
'<thead>'+
'<tr>'+
'<th>一</th>'+
'<th>二</th>'+
'<th>三</th>'+
'<th>四</th>'+
'<th>五</th>'+
'<th>六</th>'+
'<th>七</th>'+
'</tr>'+
'</thead>'+
'<tbody>';
for(var i = 0;i<monthDate.days.length;i++){
var date = monthDate.days[i];
if(i%7 === 0){
html += '<tr>';
}
if(date.date<=0){
html += '<td data-date = ' + date.date+' class = "notThisMonth">'+ date.showDate +'</td>'
}else if(date.date>date.showDate){
html += '<td data-date = ' + date.date+' class = "notThisMonth">'+ date.showDate +'</td>'
}else if(date.showDate == today.getDate()&&monthDate.month == today.getMonth()+1&&monthDate.year == today.getFullYear()){
html += '<td data-date = ' + date.date+' class = "on">'+ date.showDate +'</td>'
}else{
html += '<td data-date = ' + date.date+'>'+ date.showDate +'</td>'
}
if(i%7 === 6){
html += '</tr>';
}
}
html += '</tbody>'+
'</table>'+
'</div>';
return html;
};
事件绑定处理
由于日期数据(包括上一月、下一月的按钮)均为动态生成,所以将事件绑定在外层 datePicker—wrapper上 ,否则的话每生成一次新的数据,都要进行事件绑定
- 为inpute 添加事件绑定 获取其位置坐标,为 datePicker 参考,展示datePicker
- 为$wrapper 添加绑定事件,代理ui-datePicker-next-btn、ui-datePicker-prev-btn 控制数据的获取及重新渲染
- 为$wrapper 添加绑定事件,代理td单元格的点击事件,获取当前单元格的日期
$input.addEventListener('click',function(){
if(isOpen){
$wrapper.classList.remove('ui-datePicker-wrapper-show');
isOpen = false;
}else{
$wrapper.classList.add('ui-datePicker-wrapper-show');
var left = $input.offsetLeft;
var top = $input.offsetTop;
var height = $input.offsetHeight;
$wrapper.style.top = top + height + 8 + 'px';
$wrapper.style.left = left + 2 +'px';
isOpen = true;
}
},false);
$wrapper.addEventListener('click',function(e){
var $target = e.target;
if(!$target.classList.contains('ui-datePicker-btn')) return;
if($target.classList.contains('ui-datePicker-prev-btn')){
datepicker.render('prev');
}else if($target.classList.contains('ui-datePicker-next-btn')){
datepicker.render('next');
}
},false);
$wrapper.addEventListener('click',function(e){
var $target = e.target;
if($target.tagName.toLowerCase() !=='td')return;
var date = new Date(monthDate.year,monthDate.month-1,$target.dataset.date);
$input.value = format(date);
$wrapper.classList.remove('ui-datePicker-wrapper-show');
isOpen = false;
},false);
one more thing
这个组件是根据慕课网DatePicker组件开发一课做的demo,用了一晚上的时间实现了课程中的功能,课程中并未特殊处理非本月日期的数据渲染 第二天优化了一下 ,处理了上述问题,并添加了鼠标滑过的动画特效
已投食GitHub
欢迎star