百度前端学院之听UI组件之日历组件

前言

前段时间全身心投入到复习,因此没有时间来写博客,这几天结束了考试,将前段时间的内容一点点赶上。

正文

imgn

先去抄了一个界面,然后开始写代码。

题目要求如下:

		组件默认一直呈显示状态
		通过某种方式选择年、月,选择了年月后,日期列表做相应切换
		通过单击某个具体的日期进行日期选择
		组件初始化时,可配置可选日期的上下限。可选日期和不可选日期需要有样式上的区别
		提供设定日期的接口,指定具体日期,日历面板相应日期选中
		提供获取日期的接口,获取日历面板中当前选中的日期,返回一个日期对象(或其他形式,自定)
任务注意事项
		示例图仅为参考,样式及交互方式不需要完全实现一致
		可以使用JQuery等类库,不可直接使用现成的日历组件
		请注意代码风格的整齐、优雅
		代码中含有必要的注释

个人爱好把组件完全独立出来,因此使用原生js来写。

html:
    <div class="datePicker">
        <div class="datePicker" style="left: 100px; display: block;">
            <div class="datePicker-header">
                <b class="datePicker-pre"></b>
                <b class="datePicker-next"></b>
                <div class="datePicker-select yearPicker">
                    <div class="date-hd">
                        <b class="date-icon"></b>
                        <span class="currYear">2016</span>
                    </div>
                    <div class="date-bd">
                        <ul class="selectYear">
                        </ul>
                    </div>
                </div>
                <div class="datePicker-select mouthPicker">
                    <div class="date-hd">
                        <b class="date-icon"></b>
                        <span class="currMouth">5</span>
                    </div>
                    <div class="date-bd">
                        <ul class="selectMouth">
                            <li><a>1</a></li>
                            <li><a>2</a></li>
                            <li><a>3</a></li>
                            <li><a>4</a></li>
                            <li><a>5</a></li>
                            <li><a>6</a></li>
                            <li><a>7</a></li>
                            <li><a>8</a></li>
                            <li><a>9</a></li>
                            <li><a>10</a></li>
                            <li><a>11</a></li>
                            <li><a>12</a></li>
                        </ul>
                    </div>
                </div>
            </div>
            <div class="datePicker-title">
                <ul>
                    <li>日</li>
                    <li>一</li>
                    <li>二</li>
                    <li>三</li>
                    <li>四</li>
                    <li>五</li>
                    <li>六</li>
                </ul>
            </div>
            <div class="datePicker-body">
                <ul class="clearfix dateContent"></ul>
            </div>
        </div>
    </div>
css:
/*
    reset
*/

body,div,b,ul,li,a{
    padding: 0;
    margin: 0;
}

li,ul,ol{
    list-style: none;
}
a{
    text-decoration: none;
}
body{
    font-family: 'Microsoft yahei';
    font-size: 14px;
}
.clearfix:after,
.clearfix:before{
    content: '';
    display: table;
}
.clearfix:after{
    clear: both;
}
.clearfix{
    *zoom:1;
    overflow: hidden;
}


.datePicker{
    position: absolute;
    z-index: 100;
    width: 250px; 
}

.datePicker-header{
    position: relative;
    height: 35px;
    line-height: 35px;
    background-color: #d9edf7;
    text-align: center;
}
.datePicker-select{
    position: relative;
    display: inline-block;
}
.datePicker-select .date-hd{
    position: relative;
    width: 80px;
    height: 25px;
    line-height: 25px;
    background: #fff;
    font-size: 12px;
}
.datePicker-select .date-hd span{
    padding-right: 10px;
}
.datePicker-select .date-icon{
    position: absolute;
    border: 6px solid transparent;
    right: 10px;
    top: 9px;
    border-top-color: #ccc;
    cursor: pointer;
}
.datePicker-select .date-icon:after{
    content: '';
    position: absolute;
    top: -8px;
    right: -7px;
    border: 7px solid transparent;
    border-top-color: #fff;
    
}

.datePicker-select .date-bd{
    position: absolute;
    top: 25px;
    width: 80px;
    display: none;
    background: #fff;
    font-size: 12px;
    border: 1px solid #d9edf7;
    border-top: none;
    margin-left: -1px;
}
.datePicker-select .date-bd ul{
    max-height: 200px;
    overflow: auto;
}

.datePicker-select .date-bd a{
    padding-right: 6px;
    color: #333;
    cursor: pointer;
}
.datePicker-select .date-bd a:hover{
    background: #d9edf7;
    color: #fff;
    display: block;
}
.datePicker-select .date-bd li{
    height: 25px;
    line-height: 25px;
}
.datePicker-select.active .date-bd{
    display: block;
}
.datePicker-pre,
.datePicker-next{
    position: absolute;
    top: 9px;
    border: 7px solid transparent;
    transition: .3s all ease-out;
    cursor: pointer;
}

.datePicker-pre{
    border-right-color: rgba(255,255,255,.6);
    left: 5px;
}
.datePicker-pre:hover{
    border-right-color: rgba(255,255,255,1);
}
.datePicker-next{
    border-left-color: rgba(255,255,255,.6);
    right: 5px;
}
.datePicker-next:hover{
    border-left-color: rgba(255,255,255,1);
}

.datePicker-title{
    border-left: 1px solid #ccc;
    border-right: 1px solid #ccc;
}
.datePicker-title ul{
    height: 30px;
    line-height: 30px;
    overflow: hidden;
}
.datePicker-body li,
.datePicker-title li{
    width: 14%;
    float: left;
    text-align: center;
    
}
.datePicker-body ul{
    border:1px solid #ccc;
    padding: 10px 0;
}
.datePicker-body li{
    height: 35px;
    line-height: 35px;
    cursor: pointer;
}
.datePicker-body li a{
    display: block;
    color: #333;
}
.datePicker-body li.active a,
.datePicker-body li:hover a{
    background-color: #d9edf7;
    color: #fff;
}

接下来直接看js代码:

window.onload = function() {

    datePickerFactory('datePicker');


    function datePickerFactory(id,year,mouth) {
        var datePickerFactory = {
            Config: {
                minYear:2000,
                maxYear:2024,
                year: 2016, 
                mouth: 5
            },
            //绑定年份和月份选择事件
            bindSelect:function(){
                var that = this;
                var yearPicker = document.querySelector(".yearPicker");
                var selectYear = document.querySelector(".selectYear");
                yearPicker.addEventListener('click', function(e) {
                    if (yearPicker.className.indexOf('active') != -1) {
                        yearPicker.className = 'datePicker-select yearPicker';
                    } else {
                        yearPicker.className = 'datePicker-select yearPicker active';
                    }
                }, false);

                selectYear.addEventListener('click', function(e) {
                    document.querySelector(".currYear").innerText =  e.target.innerText;
                    that.Config.year = e.target.innerText;
                    yearPicker.className = 'datePicker-select yearPicker active';
                    that.renderContent(that.getWeek(),that.getdate());
                }, false);

                var mouthPicker = document.querySelector(".mouthPicker");
                var selectMouth = document.querySelector(".selectMouth");

                mouthPicker.addEventListener('click', function(e) {
                    if (mouthPicker.className.indexOf('active') != -1) {
                        mouthPicker.className = 'datePicker-select mouthPicker';
                    } else {
                        mouthPicker.className = 'datePicker-select mouthPicker active';
                    }
                   
                }, false);

                selectMouth.addEventListener('click', function(e) {
                    document.querySelector(".currMouth").innerText =  e.target.innerText;
                    that.Config.mouth = e.target.innerText;
                    mouthPicker.className = 'datePicker-select mouthPicker active';
                    that.renderContent(that.getWeek(),that.getdate());
                }, false);

            },
            renderContent: function(weekDay,mouthDay) {
                var dateContent = document.querySelector(".dateContent");
                dateContent.innerHTML = '';
                //创建空的日期占位
                for (var i = 0; i < weekDay; i++) {
                    var li = document.createElement("li");
                    var a = document.createElement("a");
                    a.innerHTML = '';
                    li.appendChild(a);
                    dateContent.appendChild(li);
                }
                //正常日期
                for (var j = 1; j <= mouthDay; j++) {
                    var li = document.createElement("li");
                    var a = document.createElement("a");
                    a.innerHTML = j;
                    li.appendChild(a);
                    dateContent.appendChild(li);
                }

            },
            initYear:function(){
                var that = this;
                var selectYear = document.querySelector(".selectYear");
                for (var i = that.Config.minYear ; i <= that.Config.maxYear; i++) {
                        var li = document.createElement("li");
                        var a = document.createElement("a");
                        a.innerHTML = i;
                        li.appendChild(a);
                        selectYear.appendChild(li);
                }
            },
            //确定某个月的第一天是星期几
            getWeek: function() {
                var that = this;
                var thisDay = new Date();
                var thisYear = parseInt(that.Config.year);
                var thisMouth = parseInt(that.Config.mouth);
                //setFullYear() 方法用于设置指定年份和月份。月份从0开始计数
                thisDay.setFullYear(thisYear, thisMouth - 1, 1);
                //getDay() 方法可返回表示星期的某一天的数字。
                var weekDay = thisDay.getDay();
                return weekDay;
            },
            //某个月有多少天
            getdate: function() {
                var that = this;
                var thisYear = parseInt(that.Config.year);
                var mouth = parseInt(that.Config.mouth);
                if(mouth==1||mouth==3||mouth==5||mouth==7||mouth==8||mouth==10||mouth==12){
                    return 31;
                } else if (mouth == 4 || mouth == 6 || mouth == 9 || mouth == 11) {
                    return 30;
                } else if ((thisYear % 100 != 0 && thisYear % 4 == 0) || thisYear % 400 == 0) {
                    return 29;
                } else {
                    return 28;
                }
            },
            getFormatDate:function(){
                 var that = this;
                 var dateContent = document.querySelector(".dateContent");
                 dateContent.addEventListener('click', function(e) {
                   var formatDate = that.Config.year + '-' + that.Config.mouth + '-' + e.target.innerText;
                   console.log(formatDate);
                }, false);
            },
            init: function() {
                var that = this;
                that.initYear();
                that.renderContent(that.getWeek(),that.getdate());
                that.bindSelect();
                that.getFormatDate();

            }

        }
        return datePickerFactory.init();
    }



}

这次写的很简洁,基本就是一个需求一个方法,然后用工厂模式组合一下就出来了。关于如何把样式和js代码完全组合在一起构成一个即插即用的组件也有一点点想法,大概思路就是Shadow DOM.这也是这几天阅读的收获。

结尾

先写一篇做个开头。接下来会慢慢恢复更新。

Table of Contents