之前,我爱模板网写了一个js+dom的日历教程。最近在做一个基于element ui的项目,需要用到日历,但是需要深度定制。比如显示工作计划等。element-ui自带的日历放在node modules里面,不好修改。还不如自己写一个。
于是,我就将之前的那个js+dom的日历拿过来,基于vue进行了改造,增加了开始日期和结束日期。这样的话,无论怎么改,都得心印手了。下面是代码:
css代码:
html,body,h1,h2,h3,h4,h5,h6,hr,p,iframe,dl,dt,dd,ul,ol,li,pre,form,button,input,textarea,th,td,fieldset{margin:0; padding:0;} button{border: 0 none; background-color: rgba(0,0,0,0); cursor: pointer;} html,body{font-size:14px; color:#000; font-family:'微软雅黑'} img{border:none;} ul,ol,dl{list-style-type:none} /*浮动*/ .fl{float:left;} .fr{float:right;} /*清除浮动*/ .clear{clear:both;} .clearfix{*zoom:1;} .clearfix:before,.clearfix:after{display:table; clear:both; line-height:0; content:"";} .flex{display:flex;} .flex-start{justify-content:flex-start;} .flex-end{justify-content:flex-end;} .flex-between{justify-content:space-between;} .flex-around{justify-content: space-around;} .flex-center{justify-content:center;} .flex-top{align-items: flex-start;} .flex-middle{align-items:center;} .flex-bottom{align-items: flex-end;} .flex-grow-1{flex-grow: 1} .flex-shrink-0{flex-shrink: 0} .flex-wrap{flex-wrap:wrap;} .calendar .calendar-top{padding:12px 20px; border-bottom: 1px solid #ebeef5;} .calendar .next-prev{overflow: hidden;} .calendar .next-prev button{font-size: 12px; padding: 7px 15px; color: #606266; border: 1px solid #dcdfe6; transition: all .2s ease;} .calendar .next-prev button:first-child{border-right:0 none; border-radius: 3px 0 0 3px;} .calendar .next-prev button:last-child{border-radius: 0 3px 3px 0;} .calendar .next-prev button:hover{color: #409eff; border-color: #c6e2ff; background-color: #ecf5ff;} .calendar .calendar-body{padding: 12px 20px 35px;} .calendar .calendar-table{width:100%} .calendar .calendar-table th{padding: 12px 0; color: #606266; font-weight: 400;} .calendar .calendar-table tr:first-child td {border-top: 1px solid #ebeef5;} .calendar .calendar-table td:first-child {border-left: 1px solid #ebeef5;} .calendar .calendar-table td{border-bottom: 1px solid #ebeef5; border-right: 1px solid #ebeef5; vertical-align: top; transition: background-color .2s ease;} .calendar .calendar-table td:hover{background-color: #f2f8fe; cursor: pointer;} .calendar .calendar-table td .inner-calendar-day {box-sizing: border-box; padding: 8px; height: 85px;} .calendar .calendar-table td .today{background-color: #fb0; color: #fff; font-weight: bold;}html代码:
<div id="rootVue" style="width:800px; margin: 100px auto; padding: 25px"> <div class="calendar"> <div class="calendar-top flex flex-middle flex-between"> <div class="start-end"> {{calendarRange[0]}} 至 {{calendarRange[1]}} </div> <div class="next-prev flex flex-middle"> <button @click="prevMonth">上个月</button> <button @click="nextMonth">下个月</button> </div> </div> <div id="calendar" class="calendar-body"> <table class="calendar-table" cellpadding="0" cellspacing="0"> <tr class="calendar-day"><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr> <tbody> <tr class="calendar-day" v-for="(item,index) in calendarRenderData" :key="index"> <td v-for="(item2,index2) in item" :key="index2"> <div :class="['inner-calendar-day',item2.isToday ? 'today' : '']"v-html="item2.innerText"></div> </td> </tr> </tbody> </table> </div> </div> </div> <!--这里先引入vue,到时候会作为组件整合进element-ui--> <script src="js/vue.js"></script>js代码:
new Vue({ el: '#rootVue', data: { calendarRange: ['2020-07-01','2021-01-31'], startDate:'', endDate:'', curDate:'', calendarRenderData:[], }, created(){ this.startDate = this.calendarRange[0]; this.endDate = this.calendarRange[1]; this.curDate = this.calendarRange[0]; this.renderCalendar(); }, watch:{ }, methods:{ renderCalendar(){ const curDate = new Date(this.curDate); const curYY = curDate.getFullYear(); //年份 const curMM = curDate.getMonth(); //月份,不用来显示,不要+1 const n1str = new Date(curYY,curMM,1); //当月第一天Date const todayDate = new Date(); const todayDD = todayDate.getDate(); //今日日期 const todayMM = todayDate.getMonth(); //今日月份 为了和mm进行比较,不要+1 const todayYY = todayDate.getFullYear(); //今日年份 const firstday = n1str.getDay(); //当月第一天星期几 const m_days = new Array(31,28+this.is_leap(curYY),31,30,31,30,31,31,30,31,30,31); //各月份的总天数 const tr_str = Math.ceil((m_days[curMM] + firstday)/7); //表格所需要行数 let temp = []; for(i = 0;i < tr_str;i++) { //表格的行 let trs = []; for(k = 0;k < 7;k++) { //表格每行的单元格 let td = {}; idx = i * 7 + k; //单元格自然序列号 date_str = idx - firstday + 1; //计算日期 if(date_str <= 0 || date_str > m_days[curMM]){ td.innerText = ' '; }else{ td.innerText = curYY + '-' + this.zero(curMM + 1) + '-' + this.zero(idx - firstday + 1); } //标记今天 td.isToday = date_str === todayDD && curYY === todayYY && curMM === todayMM; trs.push(td); } temp.push(trs); } this.calendarRenderData = temp; }, prevMonth(){ let curDate = new Date(this.curDate); curDate.setMonth(curDate.getMonth() - 1); if(curDate.getTime() < new Date(this.startDate).getTime()){ alert('超出范围了'); return; } this.curDate = this.formateDate(curDate); this.renderCalendar(); }, nextMonth(){ let curDate = new Date(this.curDate); curDate.setMonth(curDate.getMonth() + 1); if(curDate.getTime() > new Date(this.endDate).getTime()){ alert('超出范围了'); return; } this.curDate = this.formateDate(curDate); this.renderCalendar(); }, formateDate(dd){ return dd.getFullYear() + '-' + this.zero(dd.getMonth()+1) + '-' + this.zero(dd.getDate()); }, is_leap(year) { return (year%100==0?res=(year%400==0?1:0):res=(year%4==0?1:0)); }, zero(n){ if(n<10){ return '0'+n; }else{ return n; } } }, mounted(){ } });