摘要:本文發(fā)布在我的博客如何寫一個(gè)日歷組件許可協(xié)議署名非商業(yè)性使用禁止演繹國際轉(zhuǎn)載請保留原文鏈接及作者。眾所周知,雖然中關(guān)于時(shí)間的有不少,我們可以通過方法多帶帶的獲取年月日時(shí)分秒毫秒貌似很多,最近寫了一個(gè)日歷以前寫的,但寫得很爛,最近優(yōu)化一下,
本文發(fā)布在我的博客如何寫一個(gè)日歷組件
許可協(xié)議: 署名-非商業(yè)性使用-禁止演繹 4.0 國際 轉(zhuǎn)載請保留原文鏈接及作者。
眾所周知,雖然javascript中關(guān)于時(shí)間的API有不少,我們可以通過方法多帶帶的獲取年、月、日、時(shí)、分、秒、毫秒...貌似很多,最近寫了一個(gè)日歷(以前寫的,但寫得很爛,最近優(yōu)化一下),所以下面簡單的記錄一下如何寫一個(gè)日歷,列出了一些我在寫日歷過程中自己封裝的一些方法效果圖
先來一張效果圖,由于沒有UI設(shè)計(jì),所以就自己簡單的設(shè)計(jì)了一個(gè)樣式(好歹我也是設(shè)計(jì)專業(yè)的,雖然已不做設(shè)計(jì)很多年),雖然略丑,但重要的是功能?。?!
思路一個(gè)日歷到底是怎樣用代碼生成的?其實(shí)觀察一下現(xiàn)有的日歷展現(xiàn)形式,可以很快的形成思路,就是:根據(jù)計(jì)算把日期號數(shù)對應(yīng)到正確的星期幾上,并按照順序逐一輸出。
以下是我的思路:
取得月份的天數(shù)
取得月份第一天是星期幾
循環(huán)對應(yīng)號數(shù)和星期幾返回一個(gè)數(shù)組對象
返回?cái)?shù)組對象的每一個(gè)子項(xiàng)至少包含:號數(shù),星期幾,然后根據(jù)情況添加:是否高亮,是否當(dāng)前月,是否節(jié)日...等屬性
方法封裝注意,為了保持方便調(diào)用javascript的方法,以及保持輸出結(jié)果符合實(shí)際,所有的方法都有如下約定:
在計(jì)算過程中
所有的關(guān)于月份都是0~11的數(shù)字
所有的關(guān)于星期都是0~6的數(shù)字
在輸出的結(jié)果中
所有關(guān)于月份的輸出默認(rèn)都是1-12的數(shù)字
所有關(guān)于星期的輸出默認(rèn)都是1-7的數(shù)字
所以在向調(diào)用方法傳遞參數(shù)過程中,月份以及星期幾統(tǒng)統(tǒng)都需要按照實(shí)際月份減一
獲取月份天數(shù)在javascript中沒有直接獲取月份天數(shù)的方法,但是它提供了一個(gè)getDate方法可以獲取日期的某一天。那我們只需要獲取月份的最后一天(下一個(gè)月的第0天)就可以得知這個(gè)月的天數(shù):
// year是要獲取的年份,閏年不一樣 // month是要獲取的月份 // 返回當(dāng)前月天數(shù) function getMonthDays(year, month){ return new Date(year, month, 0).getDate(); } getMonthDays(2016,2) //29 getMonthDays(2017,2) //28獲取星期幾
// year是要獲取的年份 // month是要獲取的月份 // 返回?cái)?shù)字幾則是星期幾 function getWeekday(year, month, day){ return new Date(year, month-1, day).getDay(); } getWeekday(2016,10,9) //輸出4,表示2016年11月9是星期4 getWeekday(2017,10,9) //輸出5,表示2017年11月9是星期5獲取月份有幾個(gè)星期
要計(jì)算月份包含幾個(gè)星期,需要兩個(gè)數(shù)據(jù):月份天數(shù)和月份第一天是星期幾,就能得到想要的結(jié)果
// year是要獲取的年份 // month是要獲取的月份 // 返回當(dāng)前月包含幾個(gè)星期 function getweeksInMonth(year, month){ var days = getMonthDays(year, month); var FirstDayWeekday = getWeekday(year, month, 1); return Math.ceil((days + FirstDayWeekday) / 7); }循環(huán)生成月份對象
有了以上方法之后,就可以通過循環(huán)生成一個(gè)簡單的月份對象了。
在這里需要注意,日歷的排序有兩種:
每一行以星期日開頭
每一行以星期開頭
// year是要獲取的年份 // month是要獲取的月份 // day天,用來判斷是否是當(dāng)前天 // type表明要星期幾開頭,0為星期一開頭,1為星期日開頭,默認(rèn)為0 // 返回當(dāng)前月包含幾個(gè)星期 const WEEKTABLE = [{ cn: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], cns: ["日", "一", "二", "三", "四", "五", "六"], en: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] },{ cn: ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], cns: ["一", "二", "三", "四", "五", "六", "日"], en: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] }] getMonthDaysArray(year, month, day, type) { if (typeof day === "undefined" && year === YEAR && month === MONTH) day = DAY; var dayArrays = []; var days = this.getMonthDays(year, month), preDays = this.getMonthDays(year, month - 1); var thisMonthFirstDayInWeek = this.getWeekday(year, month, 1), thisMonthLastDayInWeek = this.getWeekday(year, month, days); type = !type || type !== 1 ? 0 : 1; //上月在當(dāng)月日歷面板中的排列 for (var i = 0; i < thisMonthFirstDayInWeek; i++) { dayArrays.push({ dayNum: (preDays - thisMonthFirstDayInWeek + i + 1), weekDay: WEEKTABLE[type].cn[i] }) } //當(dāng)月日歷面板中的排列 for (var i = 1; i <= days; i++) { var weekDayFlag = (thisMonthFirstDayInWeek + i - 1) % 7 dayArrays.push({ dayNum: i, weekDay: WEEKTABLE[type].cn[weekDayFlag], selected: i === +day, isThisMonth: true }) }; //下月在當(dāng)月日歷面板中的排列 for (var i = 1; i <= (6 - thisMonthLastDayInWeek); i++) { var weekDayFlag = (thisMonthFirstDayInWeek + days + i - 1) % 7 dayArrays.push({ dayNum: i, weekDay: WEEKTABLE[type].cn[weekDayFlag] }) }; return dayArrays; }格式化時(shí)間
涉及到時(shí)間時(shí),常常需要把時(shí)間格式進(jìn)行轉(zhuǎn)換,為了應(yīng)對多中需求,所以自己封裝了一個(gè)
// 參數(shù)fmt必須 // date參數(shù)不必須,允許字符串和時(shí)間對象,不傳或者傳無法轉(zhuǎn)換成合法時(shí)間對象的字符串則默認(rèn)當(dāng)前時(shí)間, // 年(YYYY/yyyy)固定四個(gè)占位符 // 月(M)、日(d)、小時(shí)(h)、分(m)、秒(s)可以用 1-2個(gè)占位符,嚴(yán)格區(qū)分大小寫, // 毫秒(ms/mss)最多三個(gè)占位符,分別對應(yīng)56,056這種類型 // 例子: // (Format("yyyy-MM-dd hh:mm:ss:ms") ==> 2006-07-02 08:09:04:23 // (Format("yyyy-MM-dd hh:mm:ss:mss") ==> 2006-07-02 08:09:04:023 // (Format("yyyy-M-d h:m:s:ms") ==> 2006-7-2 8:9:4.180 function formate(fmt, date){ date = new Date(date).toString() === "Invalid Date" ? new Date() : new Date(date); var _rules = [{ rule: "[yY]{4}", value: _date.getFullYear() }, { rule: "M+", value: _date.getMonth() + 1 }, { rule: "[dD]+", value: _date.getDate() }, { rule: "h+", value: _date.getHours() }, { rule: "m+", value: _date.getMinutes() }, { rule: "s+", value: _date.getSeconds() }, { rule: "ms{1,2}", value: _date.getMilliseconds() }]; _rules.forEach(function (_r){ const rule = _r.rule, val = _r.value; fmt = fmt.replace(new RegExp(rule), function ($1) { const rLen = val.toString().length, fLen = $1.length; return (fLen !== 2 || rLen >= fLen) ? val : ["00", val].join().substr(rLen); }); }); return fmt; } //調(diào)用: var time1 = formate("YYYY/MM/DD hh:mm:ss", new Date()); //2017/11/2 11:09:20 var time2 = formate("YYYY-MM-DD", time1); //2017-11-2 var time3 = formate("MM-DD-YYYY", time2); //11-2-2017最后
附上這些方法的源碼datepicker
基于vue實(shí)現(xiàn)的一個(gè)日歷:
demovue-datepicker
源碼datePickerPanel.vue
當(dāng)然這只是最簡單的日歷輸出,思路也是超級簡單(感覺有點(diǎn)Low),如果有大神愿意分享它的經(jīng)驗(yàn)歡迎,來郵~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/89938.html
摘要:項(xiàng)目需要,需要一個(gè)日歷表組件,產(chǎn)品狗嫌棄第三方提供的組件樣式太丑,功能不全,帶刀和產(chǎn)品理論奈何產(chǎn)品有槍。無奈只能自己寫一個(gè),發(fā)布完這條博客我就提離職,再也不和產(chǎn)品多。 項(xiàng)目需要,需要一個(gè)日歷表組件,產(chǎn)品狗嫌棄第三方提供的組件樣式太丑,功能不全,帶刀和產(chǎn)品理論奈何產(chǎn)品有槍。無奈只能自己寫一個(gè),發(fā)布完這條博客我就提離職,再也不和產(chǎn)品多BB。Html=>` ...
摘要:框架開發(fā)解放了生產(chǎn)力,讓一個(gè)靜態(tài)頁面效果更逼真,也讓用戶體驗(yàn)逐漸上去,但是目前對網(wǎng)站的需求主要還是為了展示和宣傳一些東西,反觀教育機(jī)構(gòu)和政府部門的網(wǎng)站都是偏動(dòng)畫少,體現(xiàn)了公關(guān)的嚴(yán)肅性。 showImg(https://segmentfault.com/img/remote/1460000009262879?w=1183&h=522); 前言 最近很久沒有寫文章,不忙也忙的生活節(jié)奏,博客...
摘要:框架開發(fā)解放了生產(chǎn)力,讓一個(gè)靜態(tài)頁面效果更逼真,也讓用戶體驗(yàn)逐漸上去,但是目前對網(wǎng)站的需求主要還是為了展示和宣傳一些東西,反觀教育機(jī)構(gòu)和政府部門的網(wǎng)站都是偏動(dòng)畫少,體現(xiàn)了公關(guān)的嚴(yán)肅性。 showImg(https://segmentfault.com/img/remote/1460000009262879?w=1183&h=522); 前言 最近很久沒有寫文章,不忙也忙的生活節(jié)奏,博客...
摘要:框架開發(fā)解放了生產(chǎn)力,讓一個(gè)靜態(tài)頁面效果更逼真,也讓用戶體驗(yàn)逐漸上去,但是目前對網(wǎng)站的需求主要還是為了展示和宣傳一些東西,反觀教育機(jī)構(gòu)和政府部門的網(wǎng)站都是偏動(dòng)畫少,體現(xiàn)了公關(guān)的嚴(yán)肅性。 showImg(https://segmentfault.com/img/remote/1460000009262879?w=1183&h=522); 前言 最近很久沒有寫文章,不忙也忙的生活節(jié)奏,博客...
閱讀 3569·2021-11-22 15:11
閱讀 4663·2021-11-18 13:15
閱讀 2714·2019-08-29 14:08
閱讀 3594·2019-08-26 13:49
閱讀 3107·2019-08-26 12:17
閱讀 3301·2019-08-26 11:54
閱讀 3124·2019-08-26 10:58
閱讀 2043·2019-08-26 10:21