摘要:雖然大家都用過這個時間選擇控件,但是卻很少有人去研究其中原理。最近這邊本人利用閑暇時間自己寫了一個時間選擇控件,借這個時間選擇控件向各位同學們闡述這個時間選擇控件的原理。
前言
??說到這個時間選擇控件,網上有很多各式各樣的,相信很多同學們也都有用過,所以大家對這個也不陌生。雖然大家都用過這個時間選擇控件,但是卻很少有人去研究其中原理。最近這邊本人利用閑暇時間自己寫了一個時間選擇控件,借這個時間選擇控件向各位同學們闡述這個時間選擇控件的原理。我向大家演示肯定是比較簡單,相對來說更容易理解一點。但是呢,考慮到實用性,我就把這個時間選擇控件改進了一下,讓其變成了一個移動端時間選擇控件,希望同學們如果喜歡我這邊文章的話,麻煩幫個點個贊哦!不勝感謝!
項目演示 本文項目地址https://github.com/ruichengpi...
本文演示地址https://ruichengping.github.i...
本文演示效果圖--------------------------------分割線----------------------------------
完整項目地址(移動端) github地址https://github.com/ruichengpi...
演示地址https://ruichengping.github.i...
理一下思路??基于上面的效果演示圖,我們第一件事就是理清思路。很多同學呢,一開始如果做這個東西可能一頭霧水,都不知道從哪里開始入手。這里我就大家理一下。
??對這種插件的開發,我個人建議先不要急著考慮其封裝之類的情況,我們就從最簡單的開始入手。那什么是最簡單的呢?那肯定就是html+css+js的模式最簡單的。什么意思呢?我這里解釋一下,現在就是單純做一個效果,html控制骨架,css美化樣式,js實現交互,不要考慮復用性。
??既然我們選擇html+css+js先去實現效果,那么著手開始先把時間選擇控件的html的dom結構寫出來,然后用css去調整其中的樣式。html和css的內容很簡單,這里我就不把代碼貼出來,同學們看完這篇文章可以去我的github項目下中Jcalendar下learn文件夾查看。下面我們說一下交互有哪些東西。
JS交互實現??關于這個JS交互,我們首先要弄清楚這個時間選擇控件有哪些交互。我先列舉一下:
年份、月份的增加減少按鈕
根據input框的位置,設置時間選擇器的位置
根據年份、月份獲取對應的日期數據
日期的選擇
時間選擇器顯示隱藏
下面一一這些功能。
根據年份、月份獲取對應的日期數據??我們先來闡述這個功能是如何實現,這是整個時間選擇控件的基石,弄清楚這個,后面的問題都會變得簡單。初看到這個確實很難,一頭霧水,都不知道如何下手。遇到這種問題的時候,先不要考慮如何去實現,首先我們弄清楚這個日期數據是由那幾塊組成。我認真地想想,發現每一組日期數據都有這樣一個等式。
日期數據=上一月的日期+這個月的日期+下個月的日期
那為什么會這么組成呢?可能有同學們有這樣子的疑問,不急不急,聽我接下來解釋一下。
一個星期是有七天,我們最長的一個月是31天,就是4個星期余三天。如果每一行代表星期,那么五行就可以搞定了。但是看效果演示圖我們可以看出來,我們用了6行。為什么會多一行?這個問題很好解釋,并不是每一個月的第一天都是從星期天開始的,所以我們要考慮最壞的情況。如果從星期六開始,此時需要6+31=37格(換上一下,就是5行多2格)。為了滿足這種最壞的情況,我們就需要6行了。
通過上面解釋,我們可以發現有一個特例并不滿足這個等式。那就是這個月第一天是從星期天開始的。不過這個特例并不影響我們用這種思路去思考問題,所以我們可以不管這個特例。下面我就看一下,這每一塊數據是如何得到的。
上個月關于得出這塊數據,我們先不要考慮其具體組成。首先考慮的是個數,需要幾個我們給它弄幾個。怎么知道需要多少個呢?很簡單,弄清楚這個月的第一天是星期幾就可以了。
/** *獲取currentYear年currentMonth月的第一天是星期幾 *month參數是要比實際上少一天的 *0 代表星期天 6代表星期六 **/ new Date(currentYear,currentMonth-1,1).getDay();
當我得出需要幾個上一月日期數據之后,我們還需要一樣東西。那就是上一個月的最后一天,根據這個來往前推。
/** *獲取currentYear年currentMonth月的最后一天的日期 *month參數是要比實際上少一天的 **/ new Date(currentYear,currentMonth-1,0).getDate();這個月
這個月的日期數據相比較上一個就簡單多了,只需要知道這一月的第一天和最后一天即可。
//獲取currentYear年currentMonth月的第一天的日期 new Date(currentYear,currentMonth-1,1).getDate(); //獲取currentYear年currentMonth月的最后一天的日期 new Date(currentYear,currentMonth,0).getDate();下一月
這塊數據也非常簡單,總共7*6=42格,剩下幾格就往里面填幾個。我們這里只需要知道下一個月的第一天是多少就行了。
//獲取currentYear年currentMonth月的下一月的一天的日期 new Date(currentYear,currentMonth,1).getDate();最終的JS代碼
//根據年,月獲取日數組 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對象 var firstDateObj = new Date(year, month - 1, 1); //獲取該月第一天對應的星期幾 var firstDateWeekDay = firstDateObj.getDay(); //獲取該月最后一天的Date對象 var lastDateObj = new Date(year, month, 0); //獲取該月最后一天的日期 var lastDate = lastDateObj.getDate(); //獲取上一個月最后一天的Date對象 var lastDateOfPrevMonthObj = new Date(year, month - 1, 0); //獲取上一個月最后一天的日期 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 } }年份、月份的增加減少按鈕
??這塊沒有難的點,需要注意的就是臨界值得判斷。比如說12月再加1個月,不能變成13月,而是年份加1,月份置為1.
根據input框的位置,設置時間選擇器的位置??這塊內容也很簡單,弄清楚left值和top值是如何計算的即可。
top值=input輸入框到瀏覽器窗口頂部的距離+input自身的高度
left值=input輸入框到瀏覽器窗口左邊的距離
??上面需要注意的是距離游覽器而不是整個文檔,因為我們用的fixed而不是absolute。
日期的選擇??這里沒有難點,但是有一個新手非常容易犯錯的錯誤。在為日期綁定事件的時候,新手很容易就會找到當前頁面所有日期給它綁定事件。這樣顯然是行不通的,因為日期數據是不斷變得,也就是日期這些dom元素是會替換了的,之前綁定的事件也就不見了,所以我建議大家用事件委托機制??赡軙腥朔瘩g我,每一天改變年份和月份的時候在重新綁定一次不就完了,當然這樣也是可以的。但是不建議,簡單的事情不要復雜化,無端增加開銷。
時間選擇器顯示隱藏??這個小功能點,很簡單,沒啥可講。需要注意多個實例并且只有一個時間選擇器的dom結構的情況下,你該如何設計你的顯示隱藏。
結語??到這里我們就把整個時間選擇控件實現整個思路都理了一遍,相信同學們已經知道如何實現一個時間選擇控件了??烊プ约簞邮肿鲆粋€自己專屬的時間選擇控件吧!(ps:如果覺得本文寫的不錯,請記得點贊哦?。?/p>
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87225.html
摘要:前端日報精選中的操作符譯理解教程構建一個預渲染友好的應用示例譯如何學習開發如何編寫輕量級框架中文譯后臺運行實戰手冊分析器入門博客眾成翻譯一款簡單到極致的數據流框架使用組件的四個技巧關鍵請求教程奇舞周刊第期前端路上的旅行如何只用完 2017-08-12 前端日報 精選 JSX中的spread操作符【譯】理解Service WorkerVue.js教程: 構建一個預渲染SEO友好的應用示例...
閱讀 1408·2021-09-23 11:21
閱讀 3105·2019-08-30 14:14
閱讀 3187·2019-08-30 13:56
閱讀 4136·2019-08-30 11:20
閱讀 1949·2019-08-29 17:23
閱讀 2765·2019-08-29 16:14
閱讀 1693·2019-08-28 18:18
閱讀 1490·2019-08-26 12:14