vue超简洁双日历组件 发表于 2018-09-24 看了那么多的日历组件,没有一个满意的 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253<template> <div> <!--<div class="hide"> <mcalendar :child="date0"></mcalendar> <mcalendar :child="date1"></mcalendar> </div>--> <div> <mdatapick :child='mdatapickdata' @cllback="callback"></mdatapick> </div> </div></template><script> import '@/assets/css/reset.less' import mcalendar from './mdata' import mdatapick from './mdatapick' export default { data() { return { // date0: { // now: "2018-09-05", // end: "2018-09-28", // callback: function(d) { // console.log(d); // } // }, // date1: { // now: "2018-11-25", // start: "2018-11-05", // callback: function(d) { // console.log(d); // } // }, mdatapickdata: { start: "2018-09-29", end: "2018-10-18" } } }, methods: { callback(startDate, endDate) { this.mdatapickdata.start=startDate; this.mdatapickdata.end=endDate; } }, components: { mcalendar, mdatapick } }</script><style></style> 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409<template> <div class="m_calender"> <input type="text" class="date_input" readonly="readonly" v-model="dataMsg" @click="toggleShow"> <div class="datamain" v-if="open"> <div class="datacon"> <div class="con"> <div class="date_main"> <div class="title"> <div class="time">开始日期</div> <div class="timenum">{{start}}</div> </div> <div class="date_top"> <em class="prev_month hoverhands" @click="prev('start')"></em> <p> <span class="top_month">{{getMonthText(startMonth)}}</span> <span class="top_year">{{startYear}}</span> </p> <em v-if="startNext" class="next_month hoverhands" @click="next('start')"></em> </div> <div class="date_week"> <em>周日</em> <em>周一</em> <em>周二</em> <em>周三</em> <em>周四</em> <em>周五</em> <em>周六</em> </div> <div class="date_day"> <em v-for="s in startlist" :class="s.className" @click="clickDate(s,'start')">{{ s.num }}</em> </div> </div> </div> <div class="con"> <div class="date_main"> <div class="title"> <div class="time">结束日期</div> <div class="timenum">{{end}}</div> </div> <div class="date_top"> <em v-if="endPrev" class="prev_month hoverhands" @click="prev('end')"></em> <p> <span class="top_month">{{getMonthText(endMonth)}}</span> <span class="top_year">{{endYear}}</span> </p> <em class="next_month hoverhands" @click="next('end')"></em> </div> <div class="date_week"> <em>周日</em> <em>周一</em> <em>周二</em> <em>周三</em> <em>周四</em> <em>周五</em> <em>周六</em> </div> <div class="date_day"> <em v-for="s in endlist" :class="s.className" @click="clickDate(s,'end')">{{ s.num }}</em> </div> </div> </div> </div> <div class="databtn"> <div class="btn hoverhands" @click="toggleShow">取消</div> <div class="btn active hoverhands" @click="Determine">确定</div> </div> </div> </div></template><script> export default { props: ["child"], data: function() { return { open: false, start: this.child.start, startYear: '', startMonth: '', startFirstWeek: '', startDaySum: '', startlist: [], startNext:true, end: this.child.end, endYear: '', endMonth: '', endFirstWeek: '', endDaySum: '', endlist: [], endPrev:true } }, computed: { activeStartData() { return new Date(this.start).getTime(); }, activeEndData() { return new Date(this.end).getTime(); }, dataMsg() { if(this.child) { return `${this.child.start} ~ ${this.child.end}` } }, check(tag) { var startTime = new Date(`${this.startYear}-${this.checkVal(this.startMonth)}-01`).getTime(); var endTime = new Date(`${this.endYear}-${this.checkVal(this.endMonth)}-01`).getTime(); if(endTime <= startTime) { return false; } return true; } }, mounted() { var startDate = new Date(this.start); this.startYear = startDate.getFullYear(); this.startMonth = startDate.getMonth() + 1; var endDate = new Date(this.end); this.endYear = endDate.getFullYear(); this.endMonth = endDate.getMonth() + 1; this.init(); }, methods: { toggleShow() { this.open = !this.open; }, init() { this.startFirstWeek = new Date(`${this.startYear}-${this.checkVal(this.startMonth)}-01`).getDay(); this.startDaySum = this.getMonthDaySum(`${this.startYear}-${this.checkVal(this.startMonth)}-01`); this.startlist = this.initDate(this.startFirstWeek, this.startDaySum, this.startYear, this.startMonth, this.activeStartData); this.endFirstWeek = new Date(`${this.endYear}-${this.checkVal(this.endMonth)}-01`).getDay(); this.endDaySum = this.getMonthDaySum(`${this.endYear}-${this.checkVal(this.endMonth)}-1`); this.endlist = this.initDate(this.endFirstWeek, this.endDaySum, this.endYear, this.endMonth, this.activeEndData) }, prev(tag) { if(tag == 'end') { if(!this.check) { return false; } } this[tag + 'Month']--; if(!this[tag + 'Month']) { this[tag + 'Month'] = 12; this[tag + 'Year']--; } this.$nextTick(() => { this.init(); }) }, next(tag) { if(tag == 'start') { if(!this.check) { return false; } } this[tag + 'Month']++; if(this[tag + 'Month'] > 12) { this[tag + 'Month'] = 1; this[tag + 'Year']++; } this.$nextTick(() => { this.init(); }) }, getMonthDaySum(val) { //获取当前月有多少天 var curDate = new Date(val); var curMonth = curDate.getMonth(); curDate.setMonth(curMonth + 1); curDate.setDate(0); return curDate.getDate(); }, initDate(FirstWeek, DaySum, Year, Month, activeData) { var list = []; for(var i = 1; i <= FirstWeek; i++) { var Dates = new Date(`${Year}-${this.checkVal(Month)}-01`); Dates.setDate(i - FirstWeek); list.push({ "className": "disabled", "num": Dates.getDate(), "date": `${Year}-${this.checkVal(Month-1)}-${Dates.getDate()}` }) } for(var i = 1; i <= DaySum; i++) { var isActive = new Date(`${Year}-${this.checkVal(Month)}-${this.checkVal(i)}`).getTime() == activeData; list.push({ "className": isActive ? 'on' : '', "num": i, "date": `${Year}-${this.checkVal(Month)}-${this.checkVal(i)}` }) } var nextData = new Date(`${Year}-${this.checkVal(Month)}-${DaySum}`).getDay(); for(var i = 1; i <= 6 - nextData; i++) { list.push({ "className": "disabled", "num": i, "date": `${Year}-${this.checkVal(Month+1)}-${this.checkVal(i)}` }) } return list; }, checkVal(num) { num = +num; return +num < 10 ? "0" + num : '' + num; }, clickDate(val, tag) { if(val.className !== 'disabled') { this[tag] = val.date; this.$nextTick(() => { this.init(); }) } }, Determine() { this.toggleShow(); this.$emit("cllback", this.start, this.end) }, getMonthText(m) { return ['', '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'][m] } } }</script><style lang="less" scoped> .m_calender { position: relative; display: block; margin: 0 auto; .date_input { margin: 0 auto; width: 200px; border: 1px solid red; text-align: center; height: 20px; line-height: 20px; cursor: pointer; display: block; color: #484848; font-size: 12px; } .datamain { border: 1px solid #E6E6E6; position: absolute; left: 50%; top: 30px; transform: translateX(-50%); &::before { content: ''; position: absolute; left: 50%; transform: translateX(-50%); top: -18px; width: 0; height: 0; border-top: 9px solid rgba(0, 0, 0, 0); border-right: 9px solid rgba(0, 0, 0, 0); border-bottom: 9px solid #E6E6E6; border-left: 9px solid rgba(0, 0, 0, 0); } &::after { content: ''; position: absolute; left: 50%; transform: translateX(-50%); top: -15px; width: 0; height: 0; border-top: 8px solid rgba(0, 0, 0, 0); border-right: 8px solid rgba(0, 0, 0, 0); border-bottom: 8px solid white; border-left: 8px solid rgba(0, 0, 0, 0); } .datacon { display: flex; .con { margin: 5px 10px; .date_main { width: 232px; background: #FFFFFF; z-index: 20; .title { padding: 8px 4px; display: flex; justify-content: space-between; align-items: center; font-size: 14px; .time { color: #939393; } .timenum { color: #333333; } } .date_top { height: 28px; line-height: 28px; padding: 0 6px; display: flex; justify-content: space-around; align-items: center; em { width: 14px; font-style: normal; margin: 9px 4px; &.prev_month { width: 0px; height: 0px; border-top: 7px solid rgba(0, 0, 0, 0); border-bottom: 7px solid rgba(0, 0, 0, 0); border-right: 7px solid #A1A1A1; border-left: 7px solid rgba(0, 0, 0, 0); } &.next_month { width: 0px; height: 0px; border-top: 7px solid rgba(0, 0, 0, 0); border-bottom: 7px solid rgba(0, 0, 0, 0); border-left: 7px solid #A1A1A1; border-right: 7px solid rgba(0, 0, 0, 0); } } p { width: 100px; flex: 1; font-size: 12px; font-weight: 700; text-align: center; span { width: 40px; display: inline-block; text-align: center; } } } .date_week { height: 24px; em { box-sizing: border-box; font-style: normal; width: 33px; height: 24px; line-height: 24px; display: block; float: left; color: #484848; font-size: 12px; text-align: center; } } .date_day { overflow: hidden; border: 1px solid #E6E6E6; em { font-style: normal; width: 32px; height: 20px; line-height: 20px; display: block; float: left; color: #484848; font-size: 12px; text-align: center; border-right: 1px solid #E6E6E6; cursor: pointer; &:nth-child(7n) { border-right: 0px solid #E6E6E6; } &.on { color: #FFFFFF; background-color: #E76E00; } &.disabled { color: #CCCCCC; background-color: #FFFFFF; cursor: default; } } } } } } .databtn { text-align: right; display: flex; justify-content: flex-end; align-items: center; padding: 5px 0px 11px; .btn { display: flex; justify-content: center; align-items: center; box-sizing: border-box; width: 56px; height: 24px; border: 1px solid red; font-size: 12px; border: 1px solid #E6E6E6; border-radius: 2px; &.active { color: wheat; margin: 0px 8px; background: #EE6E25; } } } } }</style>