當我們需要在頁面中顯示某月的事項,或是選擇某一段日期時,常常要使用到日歷組件。這一組件同樣有着許多現成的類庫,然而親自動手開發一個日歷,從中了解其實現原理也是非常必要的。在本例中我們就將制作一款非常經典的日歷組件。
更多精彩內容歡迎訪問我的個人博客皮皮豬:http://www.zhsh666.xyz或者http://www.zh66.club期待您的光臨哦!我是皮皮豬,感謝各位光臨,能為您排憂解難小站深感榮幸!祝您生活愉快!
1. 創建DOM代碼
本例的HTML代碼如下:
<div class="calendar">
<div class="title">
<h1 class="green" id="calendar-title">Month</h1>
<h2 class="green small" id="calendar-year">Year</h2>
<a href="" id="prev">Prev Month</a>
<a href="" id="next">Next Month</a>
</div>
<div class="body">
<div class="lightgrey body-list">
<ul>
<li>MON</li>
<li>TUE</li>
<li>WED</li>
<li>THU</li>
<li>FRI</li>
<li>SAT</li>
<li>SUN</li>
</ul>
</div>
<div class="darkgrey body-list">
<ul id="days">
</ul>
</div>
</div>
</div>
由以上代碼可見,日歷的最外層是一個類名為calendar的div元素,其內部包含了兩大部分,分別是日歷頂部的標題區域,其類名為title,以及其下方的日期區域,其類名為body。
在title中包含了當前所選日期的月份、年份,其id分別為calendar-title和calendar-year,此外該元素還包括了prev和next兩個按鈕,分別用於切換選擇上一月和下一月。
在body中首先包含了一個周一到周日的英文表頭,它們放在一個ul元素中。在表頭之后是另一個div元素,用於顯示日歷主體。其中,日歷所選月份的每一天都將顯示在該元素內部的days列表中。
2. CSS樣式
本例中大部分的基礎CSS樣式省略介紹,在此僅介紹其中的body-list類。該類用於設置日歷表頭和日期數據的柵格顯示。我們將整個ul元素的寬度設置為100%,並將其除以7,就可以得到每一個li元素的寬度,即14.28%,將這些元素左浮動顯示,就可以得到日期的7列顯示,樣式代碼如下:
.calendar{
width:450px;
height:350px;
background:#fff;
box-shadow:0px 1px 1px rgba(0,0,0,0.1);
}
.body-list ul{
width:100%;
font-family:arial;
font-weight:bold;
font-size:14px;
}
.body-list ul li{
width:14.28%;
height:36px;
line-height:36px;
list-style-type:none;
display:block;
box-sizing:border-box;
float:left;
text-align:center;
}
此外,我們為今天、今天之前及今天之后的日期分別創建了不同的類。其中,用淺灰色來顯示過去的日期,深灰色來顯示將來的日期,日期當天則使用淺綠色背景、綠色文字加以顯示,樣式代碼如下:
.lightgrey{
color:#a8a8a8; /*淺灰色*/
}
.darkgrey{
color:#565656; /*深灰色*/
}
.green{
color:#6ac13c; /*綠色*/
}
.greenbox{
border:1px solid #6ac13c;
background:#e9f8df; /*淺綠色背景*/
}
日歷組件的初始顯示效果如下圖所示。
3. JavaScript生成日歷
接着使用JavaScript來動態生成日歷信息。首先,我們要做一些前期的准備工作。由於閏年和非閏年的二月天數是不一樣的,在此我們為這兩種年份分別創建數組,以便於獲取每個月的天數,同時為每個月份的英文名創建相應的數組變量,代碼如下:
var month_olympic = [31,29,31,30,31,30,31,31,30,31,30,31];
var month_normal = [31,28,31,30,31,30,31,31,30,31,30,31];
var month_name = ["January","Febrary","March","April","May","June","July","Auguest","September","October","November","December"];
然后,為頁面中的各種元素創建變量,以便於后續的引用,代碼如下:
var holder = document.getElementById("days");
var prev = document.getElementById("prev");
var next = document.getElementById("next");
var ctitle = document.getElementById("calendar-title");
var cyear = document.getElementById("calendar-year");
創建一個Date對象來獲取當前的日期時間,並通過getFullYear()方法來獲取當前年份,getMonth()方法來獲取月份,getDate()方法來獲取當前日期。代碼如下:
var my_date = new Date();
var my_year = my_date.getFullYear();
var my_month = my_date.getMonth();
var my_day = my_date.getDate();
我們要實現日歷的排布,最關鍵的問題是要知道某一月第一天究竟是星期幾,然后才可以根據當月的天數來依次排列其后的日期。在此,專門為該功能創建一個函數,代碼如下:
//獲取某年某月第一天是星期幾
function dayStart(month, year) {
var tmpDate = new Date(year, month, 1);
return (tmpDate.getDay());
}
此外,我們也創建一個相應的函數來獲取某月的總天數,代碼如下:
//計算某年是不是閏年,通過求年份除以4的余數即可
function daysMonth(month, year) {
var tmp = year % 4;
if (tmp == 0) {
return (month_olympic[month]);
} else {
return (month_normal[month]);
}
}
然后,創建一個refreshDate函數來生成月份顯示,代碼如下:
function refreshDate(){
var str = "";
var totalDay = daysMonth(my_month, my_year); //獲取該月總天數
var firstDay = dayStart(my_month, my_year); //獲取該月第一天是星期幾
var myclass;
for(var i=1; i<firstDay; i++){
str += "<li></li>"; //為起始日之前的日期創建空白節點
}
for(var i=1; i<=totalDay; i++){
if((i<my_day && my_year==my_date.getFullYear() && my_month==my_date.getMonth()) || my_year<my_date.getFullYear() || ( my_year==my_date.getFullYear() && my_month<my_date.getMonth())){
myclass = " class='lightgrey'"; //當該日期在今天之前時,以淺灰色字體顯示
}else if (i==my_day && my_year==my_date.getFullYear() && my_month==my_date.getMonth()){
myclass = " class='green greenbox'"; //當天日期以綠色背景突出顯示
}else{
myclass = " class='darkgrey'"; //當該日期在今天之后時,以深灰字體顯示
}
str += "<li"+myclass+">"+i+"</li>"; //創建日期節點
}
holder.innerHTML = str; //設置日期顯示
ctitle.innerHTML = month_name[my_month]; //設置英文月份顯示
cyear.innerHTML = my_year; //設置年份顯示
}
refreshDate(); //執行該函數
測試頁面,日歷顯示效果如下圖所示。
4. 添加交互動作
最后,我們為prev和next元素分別創建onclick事件函數,使得每點擊一次prev,則將當前月份減去1,並調用refreshDate函數刷新日歷顯示。當月份數值小於0時,則使年份減去1,並使月份變為11,使日歷顯示為前一年的12月。next的功能與其恰好相反。代碼如下:
prev.onclick = function(e){
e.preventDefault();
my_month--;
if(my_month<0){
my_year--;
my_month = 11;
}
refreshDate();
}
next.onclick = function(e){
e.preventDefault();
my_month++;
if(my_month>11){
my_year++;
my_month = 0;
}
refreshDate();
}
測試頁面,日歷中前一月、后一月的切換效果如下圖所示。
下載源文件:https://cloud.ecnu.edu.cn/p/DVF08RwQGRi6Aw
最后,希望這篇文章對大家自定義開發頁面中的日歷組件有所幫助!