1. 程式人生 > >js實現日歷

js實現日歷

res 實現 type 開始 new 第一天 bubuko alt 星期幾

有這樣一個普通的日歷需求
技術分享圖片

第一反應就是找插件,結果找到了,但是改起來非常麻煩,然後查下實現的原理,發現原來很簡單,於是自己實現了一個。
首先分析一下這個組件,每頁顯示的是

當前月的所有日期及所占據的行剩下的格子所屬的上一個月的最後幾天或下一個月的前幾天。

然後,神奇的Date類型原來可以這樣獲取日期實例:

new Date(2018,4,0)  // 2018年5月第一天的Date實例
new Date(2018,4,0)  // 2018年4月最後一天的Date實例
new Date(2018,4,-1)  // 2018年4月倒數第二天的Date實例
new Date(2018,4,32)  // 2018年6月第一天的Date實例

所以,可以這樣獲取每一頁的第一格的日期:

var monthFirstDate = new Date(2018, 4-1, 1) // 假設現在是四月
var monthFirstDay = monthFirstDate.getDay() // 本月第一天是星期幾,星期日是0,星期一是1...

// 所以如果每行第一個是星期日,則每一頁的第一格的日期:
var pageFirstDate = new Date(2018, 4-1, 1-monthFirstDay)

而本頁的下個月的日期的規律是

下個月第一個星期天之前的日期

所以,可以這樣獲取一頁日歷所有日期的Date實例

     /**
     * @function getCalendarData
     * @param  {type} opts {
     *      day: 所在月的某一天的Date實例
     * }
     * @return {type} {當頁所有日期的Date實例(數組)}
     */
    function getCalendarData (opts) {
        var opt = opts || {}
        var _day = opt.day || new Date(), // Date實例,不傳取今天
            nowMonth = _day.getMonth(),
            nowYear = _day.getFullYear(),
            nowDate = _day.getDate()

        var firstDate = new Date(nowYear, nowMonth, 1), // 本月第一天
            firstDay = firstDate.getDay(), // 本月第一天是星期幾
            activeNum = 1
        var result = []
        // 例: new Date(2018, 4, 0)結果是2018年3月31日,new Date(2018, 4, -1)結果是2018年3月30日
        while (!(isNextMonth(_day, new Date(nowYear, nowMonth, activeNum - firstDay)) &&
        new Date(nowYear, nowMonth, activeNum - firstDay).getDay() === 0)) {
            // 非(當天是下個月的日期&&當天是周日),則推入數組
            // 從new Date(nowYear, nowMonth, 1 - firstDay)開始是為了填上日歷當前頁裏的上一個月的日期
            result.push(new Date(nowYear, nowMonth, activeNum - firstDay))
            activeNum++
        }
        function isNextMonth (a, b) { // a,b為Date實例
            return (b.getFullYear() === a.getFullYear() && b.getMonth() === a.getMonth() + 1) || // 兩個月在同一年
        (b.getFullYear() === a.getFullYear() + 1 && b.getMonth() === 0 && a.getMonth() === 11) // 不在同一年
        }
    
        return result
    }

js實現日歷