用vue 編寫一個日曆組件(很是詳細-讓日曆簡單起來)

相信有很多小夥伴和我同樣一提到日曆就腦袋疼,而後去網上搜索好用的日曆組件,如element-ui什麼的,可是日曆畢竟是別人開發出來的, 和本身家ui設計出來的功能樣式畢竟不能100%類似,因此這個時候要麼就去git上找一個類似的而後去修改代碼,要麼就只能本身開發一個了,因此我也是把我本身學到的日曆組件封裝思路分享給你們;css

雖然我知道日曆組件確定已經有不少人發過文章,寫過思路了,可是我仍是想寫一下。vue

準備工做

我是選擇弄一個新的腳手架去開發,因此我是去vue-cli官網去拉取一個新的腳手架在本地,相信這個你們應該都會。 拉取成功以後npm serve 啓動;git

而後我習慣一點用less寫css樣式,因此我在裝一個less和less-loader,而後這個因人而異;github

開始

相信不少小夥伴和我同樣看到日曆以後不知道怎麼下手,如何能區分上下月和當前月呢,其實明白思路和原理以後就很簡單。vue-cli

一個日曆有的是42天有的是35天,緣由是6行或7行,7行展現的就比較全面;42天的優勢是能所有展現出上個月,當前月以及下個月,缺點是上個月和下個月佔比較多,有些冗餘,若是是35天看起來就會比較精簡,但有的月份就不能所有展現出來仍是須要42天,這個也無傷大雅,咱們就以42天爲例;npm

首先咱們須要看當前月的第一天是周幾,5月的1號就是週三,那麼就用42 - 2(這裏注意若是是週日在第一個就是42 - 周幾,若是是週一在第一個就是42 - (周幾 - 1 )剩下的就是當前月和下個月的日期了。element-ui

我建立一個公共js裏面放一些公共的方法方便在組件中調用;公共的js我就叫utils.js;
getYearMonthDay 就是utils裏面的一個公共方法,是爲了方便獲取年月日;
const getYearMonthDay =  (date) => {
 let year = date.getFullYear();
 let month = date.getMonth();
 let day = date.getDate();
 return {year, month, day};
};

computed: {
    visibleCalendar: function () {
        let calendatArr = [];
        先獲得當前的年,月,日
        let {year, month, day} = utils.getNewDate(utils.getDate(this.time.year, this.time.month, 1));
        
        獲取當月的第一天 獲得2019-5-1
        let currentFirstDay = utils.getDate(year, month, 1);
        
        獲取第一天是星期幾 獲得 3
        let weekDay = currentFirstDay.getDay();
        
        用當月的第一天減去 周幾前面幾天 這樣就能獲得上個月開始的天數 (當前月1號是週三,那麼週一就是上個月的最後兩天)
        let startTime = currentFirstDay - (weekDay - 1) * 24 * 60 * 60 * 1000;
        
        而後獲得全部的日期
        for (let i = 0; i < 42; i++) {
          calendatArr.push({
            date: new Date(startTime + i * 24 * 60 * 60 * 1000),
            year: year,
            month: month + 1,
            day: new Date(startTime + i * 24 * 60 * 60 * 1000).getDate()
          })
        };
        return calendatArr
    }
}

複製代碼

而後dom結構去v-for這個數組,這樣就能獲得一個初始的日曆了 數組

可是這樣很醜,並且不能區分出哪一天是上個月哪一天是下個月,因此咱們須要給上下月去加一下樣式來區分當前月和上下月的區分bash

<ul class="calendar-view clear">
  <li v-for="(item, index) in visibleCalendar" 
    :key="index" 
    class="date-view"
    :class="[ {'notCurrentMonth-class': !isCurrentMonth(item.date)}, {currentDay: isCurrentDay(item.date)}, ]"
    @click="handleClickDay(item, index)"
  >
    <span class="date-day" >
      {{item.day}}
    </span>
  </li>
</ul>
notCurrentMonth-class 是區分上下月的類名
currentDay 是判斷是不是今天的類名

判斷是不是當前月的方法,傳入每一天 用傳入的每一天去和當前年月作比較而後返回
isCurrentMonth (date) {
    let {year: currentYear, month: currentMonth} = utils.getYearMonthDay(utils.getDate(this.time.year, this.time.month, 1));
    let {year, month} = utils.getYearMonthDay(date);
    return currentYear == year && currentMonth == month
}
判斷是不是當前天的方法 同理
isCurrentDay (date) {
    let {year: currentYear, month: currentMonth, day: currentDay} = utils.getYearMonthDay(new Date());
    let {year, month, day} = utils.getYearMonthDay(date);
    return currentYear == year && currentMonth == month && currentDay == day;
}

複製代碼

而後給類名加一些本身喜歡的樣式就能夠愉快的區分出當前月和上下月以及今天less

如今就差左右切換和點擊今天回到當前月了,接下來就很簡單,咱們先寫兩個方法用來切換上下月

先去utils裏面建立一個新的方法用來獲取當前幾月幾日
const getDate = (year, month, day) => {
  return new Date(year, month, day);
}
在data () {
    let {year, month, day} = utils.getYearMonthDay(new Date());
    return {
        yearMonth: {year, month, day}, 
    }
}
// 上一個月 獲取當年月 用setMonth()去設置月份,而後更新yearMonth
  handlePrevMonth () {
    let prevMonth = utils.getDate(this.yearMonth.year,this.yearMonth.month,1);
    prevMonth.setMonth(prevMonth.getMonth() - 1);
    this.yearMonth = utils.getYearMonthDay(prevMonth);
  }
  // 下一個月 獲取當年月 用setMonth()去設置月份,而後更新yearMonth
  handleNextMonth () {
    let nextMonth = utils.getDate(this.yearMonth.year,this.yearMonth.month,1); 
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    this.yearMonth = utils.getYearMonthDay(nextMonth);
  }
  // 點擊回到今天 同理
  handleToday () {
    this.yearMonth = utils.getYearMonthDay(new Date());
  }
複製代碼

就這樣一個左右切換以及點擊回到今天的日曆就完成了,是否是很是很是的簡單?

gitHub 日曆地址 歡迎你們

我把詳細的代碼上傳到了個人gitHub上面,在git上面我寫的更詳細一些,也提供了一些對外的點擊事件,這樣在組件的外面能夠調用裏面的一些方法,這樣用起來更方便,若是你以爲還不錯,能夠去git上面給個星星或者是啥的,感謝你們支持,若是有說的不對的地方,歡迎指出,共同探討!

相關文章
相關標籤/搜索