用vue 編寫一個日歷組件(非常詳細-讓日歷簡單起來)

相信有不少小伙伴和我一樣一提到日歷就腦殼疼溃斋,然后去網(wǎng)上搜索好用的日歷組件梗劫,如element-ui什么的,但是日歷畢竟是別人開發(fā)出來的枪萄, 和自己家ui設計出來的功能樣式畢竟不能100%相似猫妙,所以這個時候要么就去git上找一個相似的然后去修改代碼割坠,要么就只能自己開發(fā)一個了,所以我也是把我自己學到的日歷組件封裝思路分享給大家对妄;

雖然我知道日歷組件肯定已經(jīng)有很多人發(fā)過文章剪菱,寫過思路了拴签,但是我還是想寫一下。

準備工作

我是選擇弄一個新的腳手架去開發(fā)构灸,所以我是去vue-cli官網(wǎng)去拉取一個新的腳手架在本地喜颁,相信這個大家應該都會曹阔。
拉取成功之后npm serve 啟動;

image.png

然后我習慣一點用less寫css樣式赃份,所以我在裝一個less和less-loader,然后這個因人而異漓库;

開始

image.png

相信很多小伙伴和我一樣看到日歷之后不知道怎么下手渺蒿,如何能區(qū)分上下月和當前月呢彪薛,其實明白思路和原理之后就很簡單善延。

一個日歷有的是42天有的是35天,原因是6行或7行彼妻,7行展示的就比較全面豆茫;42天的優(yōu)點是能全部展示出上個月揩魂,當前月以及下個月,缺點是上個月和下個月占比較多牵舵,有些冗余畸颅,如果是35天看起來就會比較精簡妒峦,但有的月份就不能全部展示出來還是需要42天,這個也無傷大雅窥浪,我們就以42天為例笛丙;

首先我們需要看當前月的第一天是周幾胚鸯,5月的1號就是周三,那么就用42 - 2(這里注意如果是周日在第一個就是42 - 周幾坦冠,如果是周一在第一個就是42 - (周幾 - 1 )剩下的就是當前月和下個月的日期了辙浑。

我創(chuàng)建一個公共js里面放一些公共的方法方便在組件中調(diào)用;公共的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();
        
        用當月的第一天減去 周幾前面幾天 這樣就能得到上個月開始的天數(shù) (當前月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這個數(shù)組,這樣就能得到一個初始的日歷了

image.png

但是這樣很丑奥吩,而且不能區(qū)分出哪一天是上個月哪一天是下個月哼蛆,所以我們需要給上下月去加一下樣式來區(qū)分當前月和上下月的區(qū)分

<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 是區(qū)分上下月的類名
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;
}

然后給類名加一些自己喜歡的樣式就可以愉快的區(qū)分出當前月和上下月以及今天

image.png

現(xiàn)在就差左右切換和點擊今天回到當前月了霞赫,接下來就很簡單腮介,我們先寫兩個方法用來切換上下月

先去utils里面創(chuàng)建一個新的方法用來獲取當前幾月幾日
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上面我寫的更詳細一些,也提供了一些對外的點擊事件抵代,這樣在組件的外面可以調(diào)用里面的一些方法腾节,這樣用起來更方便,如果你覺得還不錯荤牍,可以去git上面給個星星或者是啥的案腺,感謝大家支持,如果有說的不對的地方康吵,歡迎指出劈榨,共同探討!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晦嵌,一起剝皮案震驚了整個濱河市同辣,隨后出現(xiàn)的幾起案子拷姿,更是在濱河造成了極大的恐慌,老刑警劉巖旱函,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件响巢,死亡現(xiàn)場離奇詭異,居然都是意外死亡棒妨,警方通過查閱死者的電腦和手機抵乓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靶衍,“玉大人,你說我怎么就攤上這事茎芋÷簦” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵田弥,是天一觀的道長涛酗。 經(jīng)常有香客問我,道長偷厦,這世上最難降的妖魔是什么商叹? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮只泼,結果婚禮上剖笙,老公的妹妹穿的比我還像新娘。我一直安慰自己请唱,他們只是感情好弥咪,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著十绑,像睡著了一般聚至。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上本橙,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天扳躬,我揣著相機與錄音,去河邊找鬼甚亭。 笑死贷币,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的狂鞋。 我是一名探鬼主播片择,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼骚揍!你這毒婦竟也來了字管?” 一聲冷哼從身側響起啰挪,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘲叔,沒想到半個月后亡呵,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡硫戈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年锰什,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丁逝。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡汁胆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出霜幼,到底是詐尸還是另有隱情嫩码,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布罪既,位于F島的核電站铸题,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏琢感。R本人自食惡果不足惜丢间,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驹针。 院中可真熱鬧烘挫,春花似錦、人聲如沸牌捷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暗甥。三九已至喜滨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撤防,已是汗流浹背虽风。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寄月,地道東北人辜膝。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像漾肮,于是被迫代替她去往敵國和親厂抖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容