利用原生JavaScript實(shí)現(xiàn)造日歷輪子實(shí)例代碼
前言
在日常開(kāi)發(fā)中,大多數(shù)都是在和框架打交道,久而久之便遺忘了原生JS的感覺(jué),個(gè)人感覺(jué)中原生JS基礎(chǔ)還是很重要的,所以最近就利用了空余時(shí)間造一個(gè)輪子出來(lái),雖然以我的水平造出來(lái)的輪子質(zhì)量還是不太可靠的,但是我覺(jué)得用來(lái)練練手還是不錯(cuò)的,哈哈??!
So, Let's begin!
github:github.com/Zero-jian/p…
以下是日歷的樣子,是有點(diǎn)難看,講究講究,重點(diǎn)在于JS部分,嘻嘻?。。?/p>

關(guān)于日歷組件的實(shí)現(xiàn)思路
- 設(shè)置默認(rèn)參數(shù)
- 檢查節(jié)點(diǎn)參數(shù)是否傳入,否則拋出錯(cuò)誤
- 動(dòng)態(tài)創(chuàng)建顯示本日星期幾的橫軸
- 動(dòng)態(tài)創(chuàng)建日歷的日子
- 最后添加一點(diǎn)dom動(dòng)作就好
先來(lái)看看構(gòu)造函數(shù)內(nèi)容
constructor(options) {
let defaluteOptions = {
element: null, //這是節(jié)點(diǎn)
startOfWeek: 1,
strings: {
week: n => {
let map = {
0: '周日',
1: '周一',
2: '周二',
3: '周三',
4: '周四',
5: '周五',
6: '周六',
}
return map[n];
},
templateDay: `<li class="currentMonth">
<span class="dayLabel">
<span class="day"></span>
<span class="unit">日</span>
</span>
</li>`
},
days: {},
}
//賦值默認(rèn)參數(shù)
this.options = Object.assign({}, defaluteOptions, options);
//輪番就調(diào)用函數(shù)動(dòng)態(tài)創(chuàng)建dom
this.checkOptions()._generateTime()._generateWeekDay()._generateCurrentDay();
初始化創(chuàng)建Calendar類(lèi)對(duì)象的時(shí)候設(shè)置數(shù)值,賦值默認(rèn)參數(shù)以及調(diào)用方法來(lái)動(dòng)態(tài)創(chuàng)建dom,相信小伙伴們看懂這段代碼沒(méi)壓力。
該輪子我全程都是用ES6寫(xiě)的,畢竟程序員還是要跟上潮流的??!
賦值參數(shù)后開(kāi)始輪番調(diào)用函數(shù),首先調(diào)用的是**this.checkOptions()**方法,檢查節(jié)點(diǎn)是否存在
checkOptions() {
//如果節(jié)點(diǎn)不存在直接拋出錯(cuò)誤
if (!this.options.element) {
throw new Error('element is request');
}
return this;
}
接下來(lái)就是獲取當(dāng)天的年月日
畢竟是日歷,獲取當(dāng)前的年月日當(dāng)參考還是很重要的
_generateTime() {
let data = new Date(); //時(shí)間
let year = this.options.days.year = data.getFullYear(); //年份
let month = this.options.days.month = data.getMonth() + 1; //月份
let day = this.options.days.day = data.getDate(); //日子
this.options.days.countDay = 0; //日歷總?cè)兆訑?shù)為7*6=42
this.options.days.noMonth = data.getMonth() + 1; //不變的月份
this.options.days.noYear = data.getFullYear(); //不變的年份
return this;
}
創(chuàng)建星期橫軸
_generateWeekDay() {
let {
startOfWeek,
strings
} = this.options;
let calendar = document.querySelector('.calendar');
let ol = dom.create(`<ol class="weekdays"></ol>`);
calendar.appendChild(ol);
let weekIndex = this.createArray(7, startOfWeek).map((day, i) => {
let li = dom.create(`<li>${strings.week(i)}</li>`);
//判斷是否為今天
ol.appendChild(li);
});
return this;
}
dom.create是封裝好的方法,傳入模板即可創(chuàng)建并返回回來(lái)
this.createArray()也是封裝好的方法,本函數(shù)是創(chuàng)建一個(gè)長(zhǎng)度為7的數(shù)組,為什么長(zhǎng)度為7?因?yàn)橹芤坏街苋盏拈L(zhǎng)度為7啊,然后開(kāi)始使用map映射和遍歷來(lái)創(chuàng)建節(jié)點(diǎn)并添加document.body里面?。?!
唔唔唔,去到這里,星期橫軸就創(chuàng)建好了,接下來(lái)是重點(diǎn)部分了,就是創(chuàng)建對(duì)于的星期的日子日歷,其實(shí)只要掌握邏輯就好了,不過(guò)因?yàn)槲沂遣穗u,寫(xiě)的時(shí)候也有點(diǎn)掉坑,所以,哈哈,你們對(duì)我寫(xiě)的代碼參考參考就好了!!
接下來(lái)是重點(diǎn)了,就是創(chuàng)建日子
創(chuàng)建日歷日子分為三個(gè)部分,第一部分是上個(gè)月的日子,第二是本月的日子,第三部分是下個(gè)月的日子,三個(gè)部分所以把它們分別封裝起來(lái),嫑相互影響!!
話(huà)不多說(shuō),貼上代碼
//創(chuàng)建當(dāng)前月份日子
_generateCurrentDay() {
let date = this.options.days;
let calendar = document.querySelector('.calendar');
let ol = dom.create(`<ol class="days"></ol>`);
let getWeek = this._getWeekWeek(date.year, date.month-1, date.day); //星期幾
let getMonth = this._getMonth(date.year, date.month) //月份天數(shù)
let getMonthDay = this._getWeekDay(); //幾號(hào)
date.countDay = 0;
date.countDay += getMonth;
calendar.appendChild(ol);
//創(chuàng)建當(dāng)月日子模塊
let dayIndex = this.createArray(42, this.options.startOfWeek).map((day, i) => {
let li = dom.create(this.options.strings.templateDay);
let span = li.querySelector('.dayLabel>.day');
//判斷日歷起止,對(duì)本月日子進(jìn)行賦值
if (i >= getWeek && i <= (getMonth + getWeek)) {
span.textContent = i - getWeek;
}
//判斷是否為今天
if (i == (getMonthDay + getWeek) && date.noMonth == date.month && date.noYear == date.year) {
li.classList.add('today');
}
ol.appendChild(li);
});
document.querySelector('h1.date').appendChild(dom.create(`<p data-role="time">${date.year}-${date.month}-${date.day}</p>`));
this._generatePrevMonth()._generateNextMonth();
}
創(chuàng)建當(dāng)前月份日子的邏輯就是首先就是創(chuàng)建一個(gè)長(zhǎng)度為42的數(shù)組,因?yàn)?*7=42,數(shù)組下標(biāo)為0至42,然后獲取當(dāng)月的天數(shù)以及當(dāng)月一號(hào)時(shí)候是星期幾,通過(guò)計(jì)算獲取本月天數(shù)的下標(biāo)范圍,然后通過(guò)循環(huán)進(jìn)行賦值,這樣就創(chuàng)建了日歷本月的天數(shù)
然后是創(chuàng)建上個(gè)月的天數(shù)
按照慣例,貼上代碼
_generatePrevMonth() {
let date = this.options.days;
let year = date.year;
let month = date.month;
let beginWeek = this._getWeekWeek(year,month-1,1);//本月開(kāi)始星期
let countMonth = this._getMonth(year,month-1);//上月月份天數(shù)
let li = document.querySelectorAll('.dayLabel>.day');
beginWeek == 0 ? beginWeek+= 7 : ''; //如果月份開(kāi)頭為星期日,會(huì)出bug,這是防止
date.countDay += beginWeek;
this.createArray(beginWeek,this.options.startOfWeek).map((day,i)=>{
if(i<beginWeek) {
//上月總天數(shù)-本月開(kāi)始星期幾+1+i
li[i].textContent = countMonth - beginWeek + 1 + i;
}
});
return this;
}
創(chuàng)建上月的日子,首先獲取本月一號(hào)是星期幾,比如是星期三就可以知道前面空的數(shù)字分別為星期日、星期一和星期二,上月的天數(shù)能占三個(gè)位置,所以就創(chuàng)建一個(gè)長(zhǎng)度為3的數(shù)組,然后計(jì)算上月的天數(shù),然后通過(guò)邏輯判斷進(jìn)行賦值,就是如此~~~
最后就是下一個(gè)月的天數(shù)
代碼 代碼 代碼
//創(chuàng)建下個(gè)月日子
_generateNextMonth() {
let date = this.options.days;
let year = date.year;
let month = date.month;
let beginWeek = this._getWeekWeek(year,month,1);//開(kāi)始星期
let countMonth = this._getMonth(year,month+1);//下月月份天數(shù)
let li = document.querySelectorAll('.dayLabel>.day');
//data.countDay統(tǒng)計(jì)了上月和本月的日子數(shù)總量,直接減去即可
this.createArray(42-date.countDay , this.options.startOfWeek).map((day,i)=>{
li[date.countDay+i].textContent = i+1;
});
}
這個(gè)邏輯比較簡(jiǎn)單,就是用(6*7=42)42減去上月天數(shù)和本月天數(shù),剩下的位置為顯示下個(gè)月的天數(shù),所以就是這樣子?。?!
把封裝好的代碼也弄出來(lái)吧~~
//dom.create()調(diào)用
let dom = {
create(html) {
let template = document.createElement('template');
template.innerHTML = html;
return template.content.firstChild;
}
}
//this.createArray()調(diào)用
//創(chuàng)建數(shù)組節(jié)點(diǎn)
createArray(length, fill) {
let array = Array.apply(null, {
length: length
}).map(() => fill);
return array;
}
動(dòng)作切換部分
切換日子這里相對(duì)來(lái)說(shuō)就是比較簡(jiǎn)單,我直接貼代碼,你們一看就懂了
//上一個(gè)月
previousMonth() {
// this.options.days.month -= 1;
this.changeMonth('prev');
}
//下一個(gè)月
nextMonth() {
// this.options.days.month += 1;
this.changeMonth('next');
}
//回到今天
resetMonth() {
// this._generateTime();
this.changeMonth('defalut');
}
//封裝月份dom
changeMonth(status) {
let date = this.options.days;
switch(status) {
case 'prev': {
--date.month < 1 ? date.year-- ? date.month = 12 : '' : '';
break;
}
case 'next': {
++date.month > 12 ? date.year++ ? date.month = 1 : '' : '';
break;
}
case 'defalut': {
this._generateTime();
break;
}
}
//移除節(jié)點(diǎn)
this._generateCalendar();
//重新添加節(jié)點(diǎn)
this._generateCurrentDay();
}
唔唔唔,整個(gè)日歷組件下來(lái)大概就是這樣子,整個(gè)流程寫(xiě)下來(lái)感覺(jué)自己的思維還是有所進(jìn)步的,但是其實(shí)我覺(jué)得這個(gè)輪子代碼還是可以再封裝封裝和完善的,嘻嘻~~
輪子功能比較簡(jiǎn)單,所以剩下的功能就等待小伙伴們自由發(fā)揮了~~
好了,第一次寫(xiě)文章,熬夜寫(xiě)的,突然就有靈感了,不肯睡覺(jué),呵呵,,明天上班肯定是要打瞌睡了,呵呵~~~
本人是小白,從業(yè)將近一年,所以代碼上有什么錯(cuò)誤,請(qǐng)各位大神能夠指出指出,嗯嗯,完~~
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
javascript顯示倒計(jì)時(shí)控制按鈕的簡(jiǎn)單實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇javascript顯示倒計(jì)時(shí)控制按鈕的簡(jiǎn)單實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06
uniapp微信小程序自定義導(dǎo)航欄的全過(guò)程
最近一直在學(xué)習(xí)uni-app開(kāi)發(fā),由于uniapp是基于vue.js技術(shù)開(kāi)發(fā)的,所以下面這篇文章主要給大家介紹了關(guān)于uniapp微信小程序自定義導(dǎo)航欄的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
javascript:文字不間斷向左移動(dòng)的實(shí)例代碼
這篇文章介紹了javascript:文字不間斷向左移動(dòng)的實(shí)例代碼,有需要的朋友可以參考一下2013-08-08
JavaScript實(shí)現(xiàn)的XML與JSON互轉(zhuǎn)功能詳解
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的XML與JSON互轉(zhuǎn)功能,結(jié)合實(shí)例形式分析了基于javascript的xml與json相關(guān)轉(zhuǎn)換功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-02-02
使用js Math.random()函數(shù)生成n到m間的隨機(jī)數(shù)字
何使用js生成n到m間的隨機(jī)數(shù)字,主要目的是為后期的js生成驗(yàn)證碼做準(zhǔn)備,Math.random()函數(shù)返回0和1之間的偽隨機(jī)數(shù)2014-10-10
js動(dòng)態(tài)添加刪除,后臺(tái)取數(shù)據(jù)(示例代碼)
這篇文章主要是對(duì)js動(dòng)態(tài)添加刪除,后臺(tái)取數(shù)據(jù)(示例代碼)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11

