摘要:本文發布在我的博客如何寫一個日歷組件許可協議署名非商業性使用禁止演繹國際轉載請保留原文鏈接及作者。眾所周知,雖然中關于時間的有不少,我們可以通過方法多帶帶的獲取年月日時分秒毫秒貌似很多,最近寫了一個日歷以前寫的,但寫得很爛,最近優化一下,
本文發布在我的博客如何寫一個日歷組件
許可協議: 署名-非商業性使用-禁止演繹 4.0 國際 轉載請保留原文鏈接及作者。
眾所周知,雖然javascript中關于時間的API有不少,我們可以通過方法多帶帶的獲取年、月、日、時、分、秒、毫秒...貌似很多,最近寫了一個日歷(以前寫的,但寫得很爛,最近優化一下),所以下面簡單的記錄一下如何寫一個日歷,列出了一些我在寫日歷過程中自己封裝的一些方法效果圖
先來一張效果圖,由于沒有UI設計,所以就自己簡單的設計了一個樣式(好歹我也是設計專業的,雖然已不做設計很多年),雖然略丑,但重要的是功能!!!
思路一個日歷到底是怎樣用代碼生成的?其實觀察一下現有的日歷展現形式,可以很快的形成思路,就是:根據計算把日期號數對應到正確的星期幾上,并按照順序逐一輸出。
以下是我的思路:
取得月份的天數
取得月份第一天是星期幾
循環對應號數和星期幾返回一個數組對象
返回數組對象的每一個子項至少包含:號數,星期幾,然后根據情況添加:是否高亮,是否當前月,是否節日...等屬性
方法封裝注意,為了保持方便調用javascript的方法,以及保持輸出結果符合實際,所有的方法都有如下約定:
在計算過程中
所有的關于月份都是0~11的數字
所有的關于星期都是0~6的數字
在輸出的結果中
所有關于月份的輸出默認都是1-12的數字
所有關于星期的輸出默認都是1-7的數字
所以在向調用方法傳遞參數過程中,月份以及星期幾統統都需要按照實際月份減一
獲取月份天數在javascript中沒有直接獲取月份天數的方法,但是它提供了一個getDate方法可以獲取日期的某一天。那我們只需要獲取月份的最后一天(下一個月的第0天)就可以得知這個月的天數:
// year是要獲取的年份,閏年不一樣 // month是要獲取的月份 // 返回當前月天數 function getMonthDays(year, month){ return new Date(year, month, 0).getDate(); } getMonthDays(2016,2) //29 getMonthDays(2017,2) //28獲取星期幾
// year是要獲取的年份 // month是要獲取的月份 // 返回數字幾則是星期幾 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獲取月份有幾個星期
要計算月份包含幾個星期,需要兩個數據:月份天數和月份第一天是星期幾,就能得到想要的結果
// year是要獲取的年份 // month是要獲取的月份 // 返回當前月包含幾個星期 function getweeksInMonth(year, month){ var days = getMonthDays(year, month); var FirstDayWeekday = getWeekday(year, month, 1); return Math.ceil((days + FirstDayWeekday) / 7); }循環生成月份對象
有了以上方法之后,就可以通過循環生成一個簡單的月份對象了。
在這里需要注意,日歷的排序有兩種:
每一行以星期日開頭
每一行以星期開頭
// year是要獲取的年份 // month是要獲取的月份 // day天,用來判斷是否是當前天 // type表明要星期幾開頭,0為星期一開頭,1為星期日開頭,默認為0 // 返回當前月包含幾個星期 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; //上月在當月日歷面板中的排列 for (var i = 0; i < thisMonthFirstDayInWeek; i++) { dayArrays.push({ dayNum: (preDays - thisMonthFirstDayInWeek + i + 1), weekDay: WEEKTABLE[type].cn[i] }) } //當月日歷面板中的排列 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 }) }; //下月在當月日歷面板中的排列 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; }格式化時間
涉及到時間時,常常需要把時間格式進行轉換,為了應對多中需求,所以自己封裝了一個
// 參數fmt必須 // date參數不必須,允許字符串和時間對象,不傳或者傳無法轉換成合法時間對象的字符串則默認當前時間, // 年(YYYY/yyyy)固定四個占位符 // 月(M)、日(d)、小時(h)、分(m)、秒(s)可以用 1-2個占位符,嚴格區分大小寫, // 毫秒(ms/mss)最多三個占位符,分別對應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; } //調用: 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實現的一個日歷:
demovue-datepicker
源碼datePickerPanel.vue
當然這只是最簡單的日歷輸出,思路也是超級簡單(感覺有點Low),如果有大神愿意分享它的經驗歡迎,來郵~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89938.html
摘要:項目需要,需要一個日歷表組件,產品狗嫌棄第三方提供的組件樣式太丑,功能不全,帶刀和產品理論奈何產品有槍。無奈只能自己寫一個,發布完這條博客我就提離職,再也不和產品多。 項目需要,需要一個日歷表組件,產品狗嫌棄第三方提供的組件樣式太丑,功能不全,帶刀和產品理論奈何產品有槍。無奈只能自己寫一個,發布完這條博客我就提離職,再也不和產品多BB。Html=>` ...
摘要:框架開發解放了生產力,讓一個靜態頁面效果更逼真,也讓用戶體驗逐漸上去,但是目前對網站的需求主要還是為了展示和宣傳一些東西,反觀教育機構和政府部門的網站都是偏動畫少,體現了公關的嚴肅性。 showImg(https://segmentfault.com/img/remote/1460000009262879?w=1183&h=522); 前言 最近很久沒有寫文章,不忙也忙的生活節奏,博客...
摘要:框架開發解放了生產力,讓一個靜態頁面效果更逼真,也讓用戶體驗逐漸上去,但是目前對網站的需求主要還是為了展示和宣傳一些東西,反觀教育機構和政府部門的網站都是偏動畫少,體現了公關的嚴肅性。 showImg(https://segmentfault.com/img/remote/1460000009262879?w=1183&h=522); 前言 最近很久沒有寫文章,不忙也忙的生活節奏,博客...
摘要:框架開發解放了生產力,讓一個靜態頁面效果更逼真,也讓用戶體驗逐漸上去,但是目前對網站的需求主要還是為了展示和宣傳一些東西,反觀教育機構和政府部門的網站都是偏動畫少,體現了公關的嚴肅性。 showImg(https://segmentfault.com/img/remote/1460000009262879?w=1183&h=522); 前言 最近很久沒有寫文章,不忙也忙的生活節奏,博客...
閱讀 3562·2021-11-22 15:11
閱讀 4641·2021-11-18 13:15
閱讀 2708·2019-08-29 14:08
閱讀 3581·2019-08-26 13:49
閱讀 3098·2019-08-26 12:17
閱讀 3294·2019-08-26 11:54
閱讀 3118·2019-08-26 10:58
閱讀 2038·2019-08-26 10:21