Vue實(shí)現(xiàn)日歷小插件
本文實(shí)例為大家分享了Vue實(shí)現(xiàn)日歷小插件的具體代碼,供大家參考,具體內(nèi)容如下
先看下效果圖吧, 如下
源碼可見(jiàn)于我的github

實(shí)現(xiàn)關(guān)鍵點(diǎn):
1.組件的復(fù)用以及父子組件傳值
很明顯每年每個(gè)月的月歷樣式(數(shù)據(jù)不一樣)是一致的,那么自然而然思路就是把每個(gè)月作為一個(gè)公用組件進(jìn)行復(fù)用十二次,這樣就避免了多次重復(fù)的代碼。每個(gè)組件不一樣的地方在于年份和月份,而這兩個(gè)數(shù)據(jù)我們可以由父組件向子組件進(jìn)行傳值來(lái)告訴子組件。關(guān)鍵代碼如下:
<template>
<div class="wrap">
//months是一個(gè)包含十二個(gè)月名字的數(shù)組,用v-for對(duì)其進(jìn)行循環(huán)渲染,并且把月份的index傳給子組件
<div v-for='(items, index) in months' v-if="index == monthIndex">
<month :monthName='items'
:year='year' //年份傳給子組件,年份在mounted里面計(jì)算得出
:monthIndex='index' //月份傳給子組件
:day='today'//當(dāng)日日期傳給子組件
:key='index' >
</month>
</div>
</div>
</template>
//data部分
data () {
return {
monthIndex: 0,
months:['January', 'February', 'March', 'April',
'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December'],
year:-1,
day:-1,
}
},
2.實(shí)現(xiàn)默認(rèn)當(dāng)日選中并且切換月份的時(shí)候其他月份不會(huì)有選中樣式
在父組件的mounted鉤子里面我們會(huì)計(jì)算當(dāng)年當(dāng)月當(dāng)日,并傳給子組件,子組件的有個(gè)day屬性用于存儲(chǔ)父組件傳來(lái)的today的值,day屬性默認(rèn)值為-1,父組件傳值過(guò)去之后會(huì)給day屬性重新賦值
//父組件
mounted () {
let myDate = new Date();
this.monthIndex = myDate.getMonth();
this.year = myDate.getFullYear();
this.today = myDate.getDate() - 1;
},
在子組件循環(huán)渲染每天的日期的時(shí)候會(huì)設(shè)置一個(gè)動(dòng)態(tài)綁定樣式類(lèi)似于一下代碼(實(shí)際代碼略微不一樣):
//index值為0-41
<div v-for="(item, index) in days" :key='index'
class="dayIndex" @click='choose(index)'
:class="{choose: day == index}"> //動(dòng)態(tài)綁定樣式
當(dāng)data中的屬性day的值和index的值相等的時(shí)候,就會(huì)給div添加一個(gè)choose的樣式,但是這樣有一個(gè)問(wèn)題——那就是每個(gè)月的該index的div都會(huì)有這個(gè)class樣式。
解決辦法:在mounted里面做個(gè)判斷,如果為當(dāng)月,則給data里面的day賦值,否則不做改動(dòng)仍為-1,-1在循環(huán)渲染日期的時(shí)候沒(méi)有對(duì)應(yīng)的index,所以不會(huì)產(chǎn)生選中樣式。
if (new Date().getMonth() == this.monthIndex) {
this.chooseIndex = this.day + this.firstDayIndex;
}
3.如何計(jì)算本月月歷中上個(gè)月多余的天數(shù)和下個(gè)月需要加進(jìn)來(lái)的天數(shù)以及日期?、
這是該日歷里面比較復(fù)雜和關(guān)鍵的一點(diǎn),我們可以看到每個(gè)月的日歷總共需要42天,除開(kāi)本月天數(shù),肯定還會(huì)包括上個(gè)月部分日期和下個(gè)月部分日期,所以該問(wèn)題涉及以下多個(gè)因素:
1).本月1號(hào)前應(yīng)該留給上個(gè)月多少天數(shù)
2).上個(gè)月最后的日期是不一樣的,有28 29 30 31
3).本月的天數(shù)和留給下個(gè)月的天數(shù)
4).非本月的日期需要置灰
這四個(gè)問(wèn)題可以分別用下面的思路來(lái)解決:
問(wèn)題1:計(jì)算本月的1號(hào)是周幾,如果是周一那么前面應(yīng)當(dāng)留1天給上個(gè)月(日歷從周日開(kāi)始計(jì)算),如果是周二就應(yīng)當(dāng)留2天
每月1號(hào)可以用以下函數(shù)求得
new Date(year + '/' + monthIndex + '/' + '01').getDay();
問(wèn)題2:可以在data里面建立一個(gè)hash表----monthLastDay(js對(duì)象),對(duì)應(yīng)出每個(gè)月的天數(shù),那么上個(gè)月的最后一天的日期就可以用monthLastDay[monthIndex - 1]求得,其中如果上個(gè)月是二月份要單獨(dú)判斷是否為閏年
monthLastDay:{
0:31,
1:28,
2:31,
3:30,
4:31,
5:30,
6:31,
7:31,
8:30,
9:31,
10:30,
11:31
},
getMonthLastDay (year, month){
if (month != 1) {
return this.monthLastDay[month];
} else {
//this.leapyear是布爾值 它表示該年是否為閏年
if (this.leapyear) {
return 29;
} else {
return 28;
}
}
},
得到上個(gè)月最后一天的日期以及本月1號(hào)為周幾之后我們就可以知道需要填入的上個(gè)月日期有哪些了,可以往days數(shù)組(本月日歷渲染數(shù)據(jù)存儲(chǔ)數(shù)組)里push了。
問(wèn)題3:這個(gè)問(wèn)題就簡(jiǎn)單很多了,因?yàn)楸驹氯諝v一共有42天,我們?cè)谝粋€(gè)i<42的for循環(huán)里面對(duì)數(shù)組days進(jìn)行push,在push完上月日期和本月日期之后,把日期重置為1,繼續(xù)push到for循環(huán)結(jié)束就好了
//index為上個(gè)月最后一天的日期 lastDayNum為上個(gè)月剩余天數(shù)
generateDays (index, lastDayNum) {
let temp = 1;
//這個(gè)for循環(huán)是push上個(gè)月的剩余日期,
for (let i = lastDayNum; i > 0; i--) {
this.days.push([(index - i + 1).toString()]);
}
//index置1,開(kāi)始push本月天數(shù)
index = 1;
for (let i = 0; i < 42 - lastDayNum; i++) {
//閏年二月
if (this.leapyear) {
if (index <= 29) {
this.days.push(index.toString());
}
//非閏年月份
} else if (index <= this.monthLastDay[this.monthIndex]) {
this.days.push(index.toString());
//這個(gè)else是push下個(gè)月的日期
} else {
this.days.push([temp.toString()]);
temp++;
}
index++;
}
},
問(wèn)題4:在上面代碼中可以看到,在push非本月日期的時(shí)候,push進(jìn)day數(shù)組的不是字符串而是一個(gè)數(shù)組[xxx.toString],這樣就可以區(qū)分本月和非本月日期,然后在v-if里面對(duì)值進(jìn)行判斷添加class即可
<div v-for="(item, index) in days" :key='index'
class="dayIndex" @click='choose(index)'
:class="{choose: chooseIndex == index}">
//item為string 為本月日期
<div v-if="typeof(item) == 'string'">
{{item}}
</div>
//否則為非本月日期 添加class setGrey
<div v-else class="setGrey">
{{item[0]}}
</div>
</div>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- VUE實(shí)現(xiàn)日歷組件功能
- vue實(shí)現(xiàn)一個(gè)炫酷的日歷組件
- Vue.js創(chuàng)建Calendar日歷效果
- 基于Vue2-Calendar改進(jìn)的日歷組件(含中文使用說(shuō)明)
- vue實(shí)現(xiàn)簡(jiǎn)單的日歷效果
- Vue編寫(xiě)可顯示周和月模式的日歷 Vue自定義日歷內(nèi)容的顯示
- 基于Vue實(shí)現(xiàn)支持按周切換的日歷
- vue+elementUI實(shí)現(xiàn)簡(jiǎn)單日歷功能
- vue實(shí)現(xiàn)日歷備忘錄功能
- 使用Vue實(shí)現(xiàn)簡(jiǎn)單日歷效果
相關(guān)文章
利用Vue3+Element?Plus封裝公共表格組件(帶源碼)
最近公司項(xiàng)目中頻繁會(huì)使用到table表格,而且前端技術(shù)這一塊也用到了vue3來(lái)開(kāi)發(fā),所以基于element plus table做了一個(gè)二次封裝的組件,這篇文章主要給大家介紹了關(guān)于利用Vue3+Element?Plus封裝公共表格組件的相關(guān)資料,需要的朋友可以參考下2023-11-11
如何在Vue3項(xiàng)目中操作MySQL數(shù)據(jù)庫(kù)
在Vue3項(xiàng)目中使用axios發(fā)送HTTP請(qǐng)求與后端MySQL數(shù)據(jù)庫(kù)交互的步驟:1. 安裝MySQL數(shù)據(jù)庫(kù)并創(chuàng)建數(shù)據(jù)庫(kù)表;2. 后端服務(wù)器使用Node.js的mysql模塊實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)操作接口;3. Vue3項(xiàng)目中使用axios調(diào)用這些接口進(jìn)行數(shù)據(jù)交互2024-11-11
vue3輸入無(wú)效路由跳轉(zhuǎn)到指定error頁(yè)面問(wèn)題
這篇文章主要介紹了vue3輸入無(wú)效路由跳轉(zhuǎn)到指定error頁(yè)面問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
說(shuō)說(shuō)如何在Vue.js中實(shí)現(xiàn)數(shù)字輸入組件的方法
這篇文章主要介紹了說(shuō)說(shuō)如何在Vue.js中實(shí)現(xiàn)數(shù)字輸入組件的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01
解決vue項(xiàng)目router切換太慢問(wèn)題
這篇文章主要介紹了解決vue項(xiàng)目router切換太慢問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
公共Hooks封裝文件下載useDownloadFile實(shí)例詳解
這篇文章主要為大家介紹了公共Hooks封裝文件下載useDownloadFile實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
使用Element進(jìn)行前端開(kāi)發(fā)的詳細(xì)圖文教程
眾所周知Element是一套Vue.js后臺(tái)組件庫(kù),它能夠幫助你更輕松更快速地開(kāi)發(fā)后臺(tái)項(xiàng)目,下面這篇文章主要給大家介紹了關(guān)于使用Element進(jìn)行前端開(kāi)發(fā)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11

