Vue實(shí)現(xiàn)萬(wàn)年日歷的示例詳解
前言
又是一個(gè)老生常談的功能,接下來(lái)會(huì)從零實(shí)現(xiàn)一個(gè)萬(wàn)年日歷,從布局到邏輯,再到隨處可見(jiàn)的打卡功能。涉及的內(nèi)容有:
- 日歷的布局
- 日期數(shù)據(jù)的產(chǎn)生
- 年月的變化
- 連續(xù)最長(zhǎng)打卡日期
- 補(bǔ)卡邏輯
1.日歷的布局
<template> <div class="calendar"> <!-- 年份和日期變化 --> <div class="select"> <span class="select-icon select-sub" @click="changeYear(-1)">《</span> <span class="select-icon select-sub select-month" @click="changeMonth(-1)"><</span> <span>{{ currentMonth }}</span> <span class="select-icon select-add select-month" @click="changeMonth(+1)">></span> <span class="select-icon select-add" @click="changeYear(+1)">》</span> </div> <!-- 日歷標(biāo)題 --> <ul class="calendar-header"> <li v-for="(item, index) in headerData" :key="index" class="calendar-header-item"> <span>{{ item }}</span> </li> </ul> <!-- 日期內(nèi)容 --> <div class="calendar-box"> <div class="calendar-box-item" :class="{ delMark: !hasRemarkDays.includes(item) }" v-for="(item, index) in baseDateList" :key="index"> <!-- 最高層級(jí)顯示圓形日期 --> <div class="item-wrap" :class="{ hasMarked: hasRemarkDays.includes(item) }" @click="toRemark(item, currentDate)"> <span class="item-date">{{ item ? item : "" }}</span> <span class="item-patch" v-if="isShowPatch && !hasRemarkDays.includes(item) && item && item < currentDate">補(bǔ)卡</span> <span class="item-current" v-if="currentDate == item"><i></i></span> <span class="item-continue" v-if="continueMarkObj.maxDay == item">連續(xù){{ continueMarkObj.maxLen }}天</span> </div> <!-- 全遮罩背景淡橙色背景 --> <span class="all-mark" v-if="hasRemarkDays.includes(item)"></span> <!-- 左右遮罩,如果左邊無(wú)打卡,遮??;如果右邊無(wú)打卡,遮住 --> <span class="left-mark" v-if="index % 7 === 0 || !hasRemarkDays.includes(item - 1)"></span> <span class="right-mark" v-if="index % 7 === 6 || !hasRemarkDays.includes(item + 1)"></span> </div> </div> </div> </template>
2.日期數(shù)據(jù)的產(chǎn)生
computed: { // 返回當(dāng)前的實(shí)際天數(shù),從周一算起 baseDateList() { let date = new Date(this.currentMonth); let monthFlag = date.getMonth() + 1; let yearFlag = date.getFullYear(); let currentData = date.getDay(); let dayLength = new Date(yearFlag, monthFlag, 0).getDate(); // 周一之前的補(bǔ)0 let dateBaseData = []; for (let i = 0; i < currentData; i++) { dateBaseData.push(0); } // 周一之后的實(shí)際填寫(xiě) for (let i = 0; i < dayLength; i++) { dateBaseData.push(i + 1); } return dateBaseData; }, }
其中currentData表示今天是周幾,在此之前的數(shù)組都補(bǔ)充為0,dayLength表示這月共多少天,然后,全部push進(jìn)日期數(shù)據(jù)中。通過(guò)flex布局中的flex-wrap: wrap;讓其自動(dòng)換行即可。
3.年月的變化
// 修改年:當(dāng)type = +1時(shí),表示加一年,為-1時(shí)反之 changeYear(type) { let time = new Date(this.currentMonth); let year = time.getFullYear() + type; let month = time.getMonth() + 1; this.currentMonth = `${year}-${month}`; }, // 修改月:當(dāng)type = -1時(shí),表示加一月,為-1時(shí)次之 changeMonth(type) { let time = new Date(this.currentMonth); let year = time.getFullYear(); let month = time.getMonth() + 1; if (month === 12 && type > 0) { // 12月,并且是加的情況,年加1,月變?yōu)? year++ month = 1 } else if(month === 1 && type < 0) { // 1月,并且是減的情況,年減1,月變?yōu)?2 year-- month = 12 } else { // 其他情況,直接變化變量type的大小 month += type } this.currentMonth = `${year}-${month}`; },
引入type,既是加減的標(biāo)志位,又是變量的大小。
4.連續(xù)最長(zhǎng)打卡日期
getMaxDay() { let arr = this.hasRemarkDays; let buffChild = []; let max = []; for (let i = 0; i < arr.length; i++) { // 如果子集不連續(xù)了,重新進(jìn)行賦值和更新 if (buffChild.length && arr[i] - buffChild[buffChild.length - 1] > 1) { max = max.length > buffChild.length ? [...max] : [...buffChild]; buffChild = []; buffChild.push(arr[i]); continue; } // 如果不是,直接進(jìn)行累計(jì) buffChild.push(arr[i]); } return max.length > buffChild.length ? [...max] : [...buffChild]; },
假設(shè)max是最大的數(shù)組,那么,每次找到連續(xù)的數(shù)組都max進(jìn)行對(duì)比并更新。在節(jié)點(diǎn)中,通過(guò):class="{ hasMarked: hasRemarkDays.includes(item) }"的方式,為其添加hasMarked的樣式。
5.補(bǔ)卡日期
補(bǔ)卡邏輯很簡(jiǎn)單,當(dāng)前日期之前的日期,均可進(jìn)行補(bǔ)卡,然后,在觸發(fā)的方法中,通過(guò)$emit的方式向父組件傳遞需要補(bǔ)卡的日期,并觸發(fā)補(bǔ)卡邏輯。
總結(jié):日歷的實(shí)現(xiàn)主要是應(yīng)用JavaScript中Date對(duì)象的api和經(jīng)典的flex布局,而最長(zhǎng)連續(xù)打卡是常規(guī)算法最長(zhǎng)連續(xù)子序列的實(shí)現(xiàn)方式之一。
到此這篇關(guān)于Vue實(shí)現(xiàn)萬(wàn)年日歷的示例詳解的文章就介紹到這了,更多相關(guān)Vue萬(wàn)年日歷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vite?vue3多頁(yè)面入口打包以及部署踩坑實(shí)戰(zhàn)
因?yàn)槲覀児镜捻?xiàng)目是多頁(yè)面應(yīng)用,不同于傳統(tǒng)單頁(yè)面應(yīng)用,一個(gè)包就可以了,下面這篇文章主要給大家介紹了關(guān)于Vite?vue3多頁(yè)面入口打包以及部署踩坑的相關(guān)資料,需要的朋友可以參考下2022-05-05Vue中使用計(jì)算屬性的知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了一篇關(guān)于Vue中使用計(jì)算屬性的知識(shí)點(diǎn)總結(jié)內(nèi)容,對(duì)此有興趣的朋友們可以跟著學(xué)習(xí)參考下。2021-12-12Vue+OpenLayer為地圖添加風(fēng)場(chǎng)效果
這篇文章主要為大家展示了一個(gè)demo,即利用Vue和OpenLayer在地圖上面添加風(fēng)場(chǎng)效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-04-04關(guān)于elementUI select控件綁定多個(gè)值(對(duì)象)
這篇文章主要介紹了關(guān)于elementUI select控件綁定多個(gè)值(對(duì)象),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04