摘要:雖然大家都用過(guò)這個(gè)時(shí)間選擇控件,但是卻很少有人去研究其中原理。最近這邊本人利用閑暇時(shí)間自己寫了一個(gè)時(shí)間選擇控件,借這個(gè)時(shí)間選擇控件向各位同學(xué)們闡述這個(gè)時(shí)間選擇控件的原理。
前言
??說(shuō)到這個(gè)時(shí)間選擇控件,網(wǎng)上有很多各式各樣的,相信很多同學(xué)們也都有用過(guò),所以大家對(duì)這個(gè)也不陌生。雖然大家都用過(guò)這個(gè)時(shí)間選擇控件,但是卻很少有人去研究其中原理。最近這邊本人利用閑暇時(shí)間自己寫了一個(gè)時(shí)間選擇控件,借這個(gè)時(shí)間選擇控件向各位同學(xué)們闡述這個(gè)時(shí)間選擇控件的原理。我向大家演示肯定是比較簡(jiǎn)單,相對(duì)來(lái)說(shuō)更容易理解一點(diǎn)。但是呢,考慮到實(shí)用性,我就把這個(gè)時(shí)間選擇控件改進(jìn)了一下,讓其變成了一個(gè)移動(dòng)端時(shí)間選擇控件,希望同學(xué)們?nèi)绻矚g我這邊文章的話,麻煩幫個(gè)點(diǎn)個(gè)贊哦!不勝感謝!
項(xiàng)目演示 本文項(xiàng)目地址https://github.com/ruichengpi...
本文演示地址https://ruichengping.github.i...
本文演示效果圖--------------------------------分割線----------------------------------
完整項(xiàng)目地址(移動(dòng)端) github地址https://github.com/ruichengpi...
演示地址https://ruichengping.github.i...
理一下思路??基于上面的效果演示圖,我們第一件事就是理清思路。很多同學(xué)呢,一開(kāi)始如果做這個(gè)東西可能一頭霧水,都不知道從哪里開(kāi)始入手。這里我就大家理一下。
??對(duì)這種插件的開(kāi)發(fā),我個(gè)人建議先不要急著考慮其封裝之類的情況,我們就從最簡(jiǎn)單的開(kāi)始入手。那什么是最簡(jiǎn)單的呢?那肯定就是html+css+js的模式最簡(jiǎn)單的。什么意思呢?我這里解釋一下,現(xiàn)在就是單純做一個(gè)效果,html控制骨架,css美化樣式,js實(shí)現(xiàn)交互,不要考慮復(fù)用性。
??既然我們選擇html+css+js先去實(shí)現(xiàn)效果,那么著手開(kāi)始先把時(shí)間選擇控件的html的dom結(jié)構(gòu)寫出來(lái),然后用css去調(diào)整其中的樣式。html和css的內(nèi)容很簡(jiǎn)單,這里我就不把代碼貼出來(lái),同學(xué)們看完這篇文章可以去我的github項(xiàng)目下中Jcalendar下learn文件夾查看。下面我們說(shuō)一下交互有哪些東西。
JS交互實(shí)現(xiàn)??關(guān)于這個(gè)JS交互,我們首先要弄清楚這個(gè)時(shí)間選擇控件有哪些交互。我先列舉一下:
年份、月份的增加減少按鈕
根據(jù)input框的位置,設(shè)置時(shí)間選擇器的位置
根據(jù)年份、月份獲取對(duì)應(yīng)的日期數(shù)據(jù)
日期的選擇
時(shí)間選擇器顯示隱藏
下面一一這些功能。
根據(jù)年份、月份獲取對(duì)應(yīng)的日期數(shù)據(jù)??我們先來(lái)闡述這個(gè)功能是如何實(shí)現(xiàn),這是整個(gè)時(shí)間選擇控件的基石,弄清楚這個(gè),后面的問(wèn)題都會(huì)變得簡(jiǎn)單。初看到這個(gè)確實(shí)很難,一頭霧水,都不知道如何下手。遇到這種問(wèn)題的時(shí)候,先不要考慮如何去實(shí)現(xiàn),首先我們弄清楚這個(gè)日期數(shù)據(jù)是由那幾塊組成。我認(rèn)真地想想,發(fā)現(xiàn)每一組日期數(shù)據(jù)都有這樣一個(gè)等式。
日期數(shù)據(jù)=上一月的日期+這個(gè)月的日期+下個(gè)月的日期
那為什么會(huì)這么組成呢?可能有同學(xué)們有這樣子的疑問(wèn),不急不急,聽(tīng)我接下來(lái)解釋一下。
一個(gè)星期是有七天,我們最長(zhǎng)的一個(gè)月是31天,就是4個(gè)星期余三天。如果每一行代表星期,那么五行就可以搞定了。但是看效果演示圖我們可以看出來(lái),我們用了6行。為什么會(huì)多一行?這個(gè)問(wèn)題很好解釋,并不是每一個(gè)月的第一天都是從星期天開(kāi)始的,所以我們要考慮最壞的情況。如果從星期六開(kāi)始,此時(shí)需要6+31=37格(換上一下,就是5行多2格)。為了滿足這種最壞的情況,我們就需要6行了。
通過(guò)上面解釋,我們可以發(fā)現(xiàn)有一個(gè)特例并不滿足這個(gè)等式。那就是這個(gè)月第一天是從星期天開(kāi)始的。不過(guò)這個(gè)特例并不影響我們用這種思路去思考問(wèn)題,所以我們可以不管這個(gè)特例。下面我就看一下,這每一塊數(shù)據(jù)是如何得到的。
上個(gè)月關(guān)于得出這塊數(shù)據(jù),我們先不要考慮其具體組成。首先考慮的是個(gè)數(shù),需要幾個(gè)我們給它弄幾個(gè)。怎么知道需要多少個(gè)呢?很簡(jiǎn)單,弄清楚這個(gè)月的第一天是星期幾就可以了。
/** *獲取currentYear年currentMonth月的第一天是星期幾 *month參數(shù)是要比實(shí)際上少一天的 *0 代表星期天 6代表星期六 **/ new Date(currentYear,currentMonth-1,1).getDay();
當(dāng)我得出需要幾個(gè)上一月日期數(shù)據(jù)之后,我們還需要一樣?xùn)|西。那就是上一個(gè)月的最后一天,根據(jù)這個(gè)來(lái)往前推。
/** *獲取currentYear年currentMonth月的最后一天的日期 *month參數(shù)是要比實(shí)際上少一天的 **/ new Date(currentYear,currentMonth-1,0).getDate();這個(gè)月
這個(gè)月的日期數(shù)據(jù)相比較上一個(gè)就簡(jiǎn)單多了,只需要知道這一月的第一天和最后一天即可。
//獲取currentYear年currentMonth月的第一天的日期 new Date(currentYear,currentMonth-1,1).getDate(); //獲取currentYear年currentMonth月的最后一天的日期 new Date(currentYear,currentMonth,0).getDate();下一月
這塊數(shù)據(jù)也非常簡(jiǎn)單,總共7*6=42格,剩下幾格就往里面填幾個(gè)。我們這里只需要知道下一個(gè)月的第一天是多少就行了。
//獲取currentYear年currentMonth月的下一月的一天的日期 new Date(currentYear,currentMonth,1).getDate();最終的JS代碼
//根據(jù)年,月獲取日數(shù)組 function getMonthData(year, month, day) { var days = []; var today = new Date(); if (!year | !month | !day) { year = today.getFullYear(); month = today.getMonth() + 1; day = today.getDate(); } //獲取該月第一天的Date對(duì)象 var firstDateObj = new Date(year, month - 1, 1); //獲取該月第一天對(duì)應(yīng)的星期幾 var firstDateWeekDay = firstDateObj.getDay(); //獲取該月最后一天的Date對(duì)象 var lastDateObj = new Date(year, month, 0); //獲取該月最后一天的日期 var lastDate = lastDateObj.getDate(); //獲取上一個(gè)月最后一天的Date對(duì)象 var lastDateOfPrevMonthObj = new Date(year, month - 1, 0); //獲取上一個(gè)月最后一天的日期 var lastDateOfPrevMonth = lastDateOfPrevMonthObj.getDate(); //上月 for (var i = 0; i < firstDateWeekDay; i++) { var className = "available disabled"; var thisMonth = month - 1; var date = lastDateOfPrevMonth - firstDateWeekDay + i + 1; if (thisMonth === 0) { thisMonth = 1; } days.push({ "date": date, "showDate": date, "thisMonth": thisMonth, "className": className }); } //本月 for (var i = 0; i < lastDate; i++) { var className = "available"; var date = i + 1; var thisMonth = month; if (date === day) { className = "available current"; } if (today.getDate() === date && today.getFullYear() === year && today.getMonth() + 1 === month) { days.push({ "date": date, "showDate": "今天", "thisMonth": thisMonth, "className": className }); } else { days.push({ "date": date, "showDate": date, "thisMonth": thisMonth, "className": className }); } } var nextMonthLength = days.length; //下月 for (var i = 0; i < 7 * 6 - nextMonthLength; i++) { var className = "available disabled"; var date = i + 1; var thisMonth = month + 1; if (thisMonth === 13) { thisMonth = 12; } days.push({ "date": date, "showDate": date, "thisMonth": thisMonth, "className": className }); } return { "year": firstDateObj.getFullYear(), "month": firstDateObj.getMonth() + 1, "days": days } }年份、月份的增加減少按鈕
??這塊沒(méi)有難的點(diǎn),需要注意的就是臨界值得判斷。比如說(shuō)12月再加1個(gè)月,不能變成13月,而是年份加1,月份置為1.
根據(jù)input框的位置,設(shè)置時(shí)間選擇器的位置??這塊內(nèi)容也很簡(jiǎn)單,弄清楚left值和top值是如何計(jì)算的即可。
top值=input輸入框到瀏覽器窗口頂部的距離+input自身的高度
left值=input輸入框到瀏覽器窗口左邊的距離
??上面需要注意的是距離游覽器而不是整個(gè)文檔,因?yàn)槲覀冇玫膄ixed而不是absolute。
日期的選擇??這里沒(méi)有難點(diǎn),但是有一個(gè)新手非常容易犯錯(cuò)的錯(cuò)誤。在為日期綁定事件的時(shí)候,新手很容易就會(huì)找到當(dāng)前頁(yè)面所有日期給它綁定事件。這樣顯然是行不通的,因?yàn)槿掌跀?shù)據(jù)是不斷變得,也就是日期這些dom元素是會(huì)替換了的,之前綁定的事件也就不見(jiàn)了,所以我建議大家用事件委托機(jī)制??赡軙?huì)有人反駁我,每一天改變年份和月份的時(shí)候在重新綁定一次不就完了,當(dāng)然這樣也是可以的。但是不建議,簡(jiǎn)單的事情不要復(fù)雜化,無(wú)端增加開(kāi)銷。
時(shí)間選擇器顯示隱藏??這個(gè)小功能點(diǎn),很簡(jiǎn)單,沒(méi)啥可講。需要注意多個(gè)實(shí)例并且只有一個(gè)時(shí)間選擇器的dom結(jié)構(gòu)的情況下,你該如何設(shè)計(jì)你的顯示隱藏。
結(jié)語(yǔ)??到這里我們就把整個(gè)時(shí)間選擇控件實(shí)現(xiàn)整個(gè)思路都理了一遍,相信同學(xué)們已經(jīng)知道如何實(shí)現(xiàn)一個(gè)時(shí)間選擇控件了。快去自己動(dòng)手做一個(gè)自己專屬的時(shí)間選擇控件吧?。╬s:如果覺(jué)得本文寫的不錯(cuò),請(qǐng)記得點(diǎn)贊哦?。?/p>
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/87225.html
摘要:前端日?qǐng)?bào)精選中的操作符譯理解教程構(gòu)建一個(gè)預(yù)渲染友好的應(yīng)用示例譯如何學(xué)習(xí)開(kāi)發(fā)如何編寫輕量級(jí)框架中文譯后臺(tái)運(yùn)行實(shí)戰(zhàn)手冊(cè)分析器入門博客眾成翻譯一款簡(jiǎn)單到極致的數(shù)據(jù)流框架使用組件的四個(gè)技巧關(guān)鍵請(qǐng)求教程奇舞周刊第期前端路上的旅行如何只用完 2017-08-12 前端日?qǐng)?bào) 精選 JSX中的spread操作符【譯】理解Service WorkerVue.js教程: 構(gòu)建一個(gè)預(yù)渲染SEO友好的應(yīng)用示例...
閱讀 1530·2021-09-23 11:21
閱讀 3197·2019-08-30 14:14
閱讀 3272·2019-08-30 13:56
閱讀 4287·2019-08-30 11:20
閱讀 2034·2019-08-29 17:23
閱讀 2853·2019-08-29 16:14
閱讀 1781·2019-08-28 18:18
閱讀 1602·2019-08-26 12:14