1、當(dāng)前組件說明
一個用vue實現(xiàn)的簡單日歷組件罢吃,可以手動設(shè)置日歷的寬高楚午,未設(shè)置時,有默認(rèn)寬高尿招,設(shè)置后矾柜,其中的每個日期項的寬高可以根據(jù)設(shè)定的寬高自適應(yīng)、可以設(shè)置當(dāng)前選中日期就谜,可以設(shè)置時間可用范圍怪蔑,可以通過左右箭頭進行日期切換。(第一次使用簡書丧荐,代碼格式比較丑缆瓣,而且換行很高,也不知道怎么調(diào)整虹统,大家見諒)
2弓坞、組件效果展示
3、組件實現(xiàn)代碼
<template>
??<div?class="picker-box"?:style="'width:?'?+?width?+?'px;?height:?'?+?height?+?'px;'">
????<div?class="picker-tool"?:style="'height:?'?+?toolHeight?+?'px;?line-height:?'?+?toolHeight?+?'px;'">
??????<Button?type="text"?icon="ios-arrow-back"?@click="toVdpUpper()"></Button>
??????{{vdpYear?+?'年'?+?vdpMonth?+?'月'}}
??????<Button?type="text"?icon="ios-arrow-forward"?@click="toVdpLower()"></Button>
????</div>
????<div?class="picker-body"?:style="'height:?'?+?(height?-?50)?+?'px;'">
??????<div?class="picker-title"?v-for="item?in?xqList"?:key="item"?:style="itemStyles">{{item}}</div>
??????<div?class="picker-item"
????????:style="itemStyles"
????????v-for="(item,?i)?in?dateList"?:key="i"?@click="toSelect(item)"
????????:class="(item.disabled?===?false?&&?item.actived???'actived'?:'grey')?+?(item.checked???'?checked'?:?'')?+?(item.today???'?today'?:?'')?+?(item.disabled???'?disabled'?:?'')">
??????????{{item.day}}
???????</div>
??????<div?style="clear:?both;"></div>
????</div>
??</div>
</template>
<script>
export?default?{
??name:?'cDatePicker',
??props:?{
????//?要求傳入的值?必須為?yyyy-MM-dd?格式數(shù)據(jù)
????value:?{
??????type:?String
????},
? ? // 日歷顯示的寬度车荔,默認(rèn)300px
????width:?{
??????type:?Number,
??????default:?300
????},
? ???// 日歷顯示的高度渡冻,默認(rèn)300px
????height:?{
??????type:?Number,
??????default:?300
????},
? ???// 日歷工具欄的顯示高度,默認(rèn)32px
?????toolHeight:?{
??????type:?Number,
??????default:?32
????},
? ??// 日歷中每個時間項的行高
????lineHeight:?{
??????type:?Number
????},
????margin:?{
??????type:?Number,
??????default:?2
????},
????// 日歷可選范圍-開始時間
????start:?{
??????type:?String,
??????default:?''
????},
????// 日歷可選范圍-結(jié)束時間
????end:?{
??????type:?String,
??????default:?''
????}
??},
??watch:?{
????//?監(jiān)聽?外部插入的value值變化
????//?value?(n,?l)?{
????//???this.init()
????//?}
??},
??data?()?{
????return?{
??????xqList:?['日',?'一',?'二',?'三',?'四',?'五',?'六'],
??????vdpYear:?0,?//?選擇的年
??????vdpMonth:?0,?//?選擇的月
??????vdpDay:?0,?//?選擇的日
??????monthStart:?0,?//?月初
??????monthEnd:?0,?//?月末
??????monthWeek:?0,
??????dateList:?[]?//?當(dāng)前時間集合
????}
??},
??methods:?{
????//?初始化
????init?()?{
??????const?now?=?this.newDate(this.value?||?undefined)
??????this.vdpYear?=?now.getFullYear()
??????this.vdpMonth?=?now.getMonth()?+?1
??????this.vdpDay?=?this.value???now.getDate()?:?0
??????this.computePicker()
????},
????//?選中某一天
????toSelect?(item)?{
??????if?(item?&&?item.disabled?===?false)?{
????????//?//?通過重新生成dateList數(shù)據(jù)?達到改變選中效果
????????//?this.vdpDay?=?item.day
????????//?this.computePicker()
????????//?通過?直接循環(huán)修改dateList數(shù)據(jù)?達到改變選中效果
????????this.dateList?=?this.dateList.map(v?=>?{
??????????v.checked?=?false
??????????return?v
????????})
????????this.vdpDay?=?item.day
????????item.checked?=?true
????????this.$emit('input',?item.date)
????????this.$emit('on-change',?item.date,?this.newDate(item.date))
??????}
????},
????//?上一個月
????toVdpUpper?()?{
??????if?(this.vdpMonth?>?1)?{
????????this.vdpMonth--
??????}?else?{
????????this.vdpYear--
????????this.vdpMonth?=?12
??????}
??????this.vdpDay?=?0
??????this.computePicker()
????},
????//?下一個月
????toVdpLower?()?{
??????if?(this.vdpMonth?<?12)?{
????????this.vdpMonth++
??????}?else?{
????????this.vdpYear++
????????this.vdpMonth?=?1
??????}
??????this.vdpDay?=?0
??????this.computePicker()
????},
????//?計算月初忧便、月末族吻、月初是星期幾及當(dāng)前日期數(shù)據(jù)
????computePicker?()?{
??????const?yc?=?new?Date(this.vdpYear,?this.vdpMonth?-?1,?1)?//?月初
??????const?ym?=?new?Date(this.vdpYear,?this.vdpMonth,?0)?//?月末
??????this.monthStart?=?yc.getDate()
??????this.monthEnd?=?ym.getDate()
??????this.monthWeek?=?yc.getDay()
??????const?v?=?[]
??????for?(let?i?=?0;?i?<?42;?i++)?{
????????v.push(this.getVdpDay(i,?'-'))
??????}
??????this.dateList?=?v
????},
????//?獲取當(dāng)前日期?核心方法
????getVdpDay?(index,?defV)?{
??????let?_disabled?=?false
??????let?_actived?=?false
??????let?_year?=?this.vdpYear
??????let?_month?=?this.vdpMonth
??????let?_day?=?0
??????if?(this.monthWeek?===?0)?{
????????index?=?index?-?7
??????}
??????if?(index?<?this.monthWeek)?{
????????//?計算上月
????????_month--
????????if?(_month?===?0)?{
??????????_year--
??????????_month?=?12
????????}
????????_day?=?new?Date(_year,?_month,?0).getDate()?-?this.monthWeek?+?index?+?1?//?算當(dāng)前選中月的上一月?月末
??????}?else?if?(index?>?(this.monthWeek?+?this.monthEnd?-?1))?{
????????//?計算下月
????????_month++
????????if?(_month?===?13)?{
??????????_year++
??????????_month?=?1
????????}
????????_day?=?new?Date(this.vdpYear,?this.vdpMonth,?1).getDate()?+?index?-?(this.monthEnd?+?this.monthWeek)?//?算當(dāng)前選中月的下一月?月初
??????}?else?{
????????//?計算當(dāng)月
????????_day?=?this.monthStart?+?index?-?this.monthWeek
????????_actived?=?true
??????}
??????//?計算開始日期和結(jié)束日期
??????if?(this.start?||?this.end)?{
????????const?_curtm?=?new?Date(_year?+?'/'?+?_month?+?'/'?+?_day)
????????if?(this.start)?{
??????????const?_start?=?this.newDate(this.start)
??????????if?(_curtm?<?_start)?{
????????????_disabled?=?true
??????????}
????????}
????????if?(this.end)?{
??????????const?_end?=?this.newDate(this.end)
??????????if?(_curtm?>?_end)?{
????????????_disabled?=?true
??????????}
????????}
??????}
??????return?{?year:?_year,?month:?_month,?day:?_day,?date:?this.generateDateStr(_year,?_month,?_day),?checked:?this.verifyCheckDate(_year,?_month,?_day),?actived:?_actived,?today:?this.isToday(_year,?_month,?_day),?disabled:?_disabled?}?//?_disabled???(defV?||?'')?:?_day
????},
????//?生成時間字符串
????generateDateStr?(year,?month,?day)?{
??????return?year?+?'-'?+?(month?>?9???month?:?'0'?+?month)?+?'-'?+?(day?>?9???day?:?'0'?+?day)
????},
????//?驗證是否是當(dāng)前選中的日期
????verifyCheckDate?(year,?month,?day)?{
??????if?((this.value?&&?this.value?===?this.generateDateStr(year,?month,?day))?||?(this.vdpYear?===?year?&&?this.vdpMonth?===?month?&&?this.vdpDay?===?day))?{
????????return?true
??????}?else?{
????????return?false
??????}
????},
????//?驗證是否今天
????isToday?(year,?month,?day)?{
??????if?(this.generateDateStr(year,?month,?day)?===?this.formatDate(new?Date(),?'yyyy-MM-dd'))?{
????????return?true
??????}?else?{
????????return?false
??????}
????},
????//?字符串轉(zhuǎn)換?Date?解決ie11?時間兼容性問題
????newDate?(time,?defV)?{
??????let?v?=?defV?===?undefined???new?Date()?:?defV
??????if?(time)?{
????????v?=?new?Date(time.replace(/-/g,?'/'))
??????}
??????return?v
????},
????//?時間格式化?兼容IE
????formatDate?(date,?format)?{
??????if?(date)?{
????????var?time
????????if?(typeof?date?===?'string')?{
??????????time?=?new?Date(date.replace(/-/g,?'/'))
????????}?else?if?(typeof?date?===?'object')?{
??????????time?=?new?Date(date)
????????}
????????var?o?=?{
??????????'M+':?time.getMonth()?+?1,?//?月份
??????????'d+':?time.getDate(),?//?日
??????????'h+':?time.getHours(),?//?小時
??????????'m+':?time.getMinutes(),?//?分
??????????'s+':?time.getSeconds(),?//?秒
??????????'q+':?Math.floor((time.getMonth()?+?3)?/?3),?//?季度
??????????S:?time.getMilliseconds()?//?毫秒
????????}
????????if?(/(y+)/.test(format))?format?=?format.replace(RegExp.$1,?(time.getFullYear()?+?'').substr(4?-?RegExp.$1.length))
????????for?(var?k?in?o)?{?if?(new?RegExp('('?+?k?+?')').test(format))?format?=?format.replace(RegExp.$1,?(RegExp.$1.length?===?1)???(o[k])?:?(('00'?+?o[k]).substr((''?+?o[k]).length)))?}
????????return?format
??????}?else?{?return?''?}
????}
??},
??computed:?{
????itemStyles?()?{
??????const?_w?=?(this.width?/?7?-?this.margin?*?2)
??????const?_h?=?((this.height?-?this.toolHeight)?/?7?-?this.margin?*?2)
??????const?_lh?=?this.lineHeight???this.lineHeight?:?(_h?-?1)?+?'px'?//?parseInt(_h)
??????return?{?width:?_w?+?'px',?height:?_h?+?'px',?margin:?this.margin?+?'px',?'line-height':?_lh?}
????}
??},
??created?()?{
????this.init()
??}
}
</script>
<style?scoped>
.picker-box?{
??width:?100%;
??height:?100%;
??margin:?0?auto;
??font-size:?14px;
}
.picker-box?.picker-tool?{
??height:?50px;
??line-height:?50px;
??text-align:?center;
}
.picker-box?.picker-body?{
??width:?100%;
}
.picker-box?.picker-body?.picker-item,?.picker-box?.picker-body?.picker-title??{
??width:?calc(14.285714285%?-?10px);
??height:?calc(16.666666666%?-?10px);
??line-height:?2.6;
??text-align:?center;
??border:?1px?solid?#ececec;
??border-radius:?5px;
??margin:?5px;
??float:?left;
}
.picker-box?.picker-body?.picker-item?{
??cursor:?pointer;
}
.picker-box?.picker-body?.picker-title?{
??background:?#eaf0f5;
}
.picker-box?.picker-body?.grey?{
??color:?#b2b2b2;
??border:?1px?solid?#ececec;
??background:?#fbfbfb;
}
.picker-box?.picker-body?.actived?{
??color:?#3c3c3c;
??border:?1px?solid?#ececec;
}
.picker-box?.picker-body?.today?{
??background:?#d8f9d8;
??border:?1px?solid?#ececec;
}
.picker-box?.picker-body?.checked?{
??color:?#fff;
??background:?#19be6b;
??border:?1px?solid?#19be6b;
}
.picker-box?.picker-body?.disabled?{
??color:?#b2b2b2;
??background:?#f2f2f2;
??border:?1px?solid?#ececec;
??cursor:?not-allowed;
}
</style>
4、組件調(diào)用示例
<template>
??<div>
??????<cDatePicker?v-model="timeText"></cDatePicker>
??????<cDatePicker?v-model="timeText"?:start="start"?:end="end"?:width="500"?:height="500"?:tool-height="50"?:margin="5"></cDatePicker>
??</div>
</template>
<script>
import?cDatePicker?from?'./cDatePicker'
export?default?{
??components:?{
????cDatePicker
??},
??data?()?{
????return?{
??????timeText:?'2020-07-16',
??????start:?'2020-06-12',
??????end:?'2020-08-05'
????}
??}
}
</script>
5珠增、尚需待完善
a超歌、點擊年,進行年份切換
b蒂教、點擊月握础,進行月份切換。