最近公司要作一個酒店入住的小程序,不可避免的必定會使用到日曆,而小程序沒有內置的日曆組件。在網上看了一下也沒有很是適合需求的日曆,因而本身寫了一個。小程序
寫一個日曆只須要知道兩件事情:數組
因爲是酒店入住的日曆,因此須要實現以下功能:數據結構
根據最後的功能實現,我生成的每月的數據結構以下:this
{ year: 2018, month: 3, fullMonth: '03', allDays:[ { day: 1, fullDay: '01', fullDate: '2018-03-01' }, { day: 2, fullDay: '02', fullDate: '2018-03-02' }, //...... //(後面的數據同上) ] }
year就是年份,month是月份,day是日期,fullDate是完整日期。
fullMonth和fullDay本來是兩個不須要的數據,可是在點擊日期改變顏色的時候用到了,由於小程序沒有提供很好的處理數據的filter。固然這個問題也和個人我的水平有關,若是有哪位大神有更好的方法,請留言告訴我。我很是想去掉這兩個數據。code
// calendar.js文件 Page({ data: { week_list: ['日','一','二','三','四','五','六'], startDate: '', endDate: '', date_click: 0 }, // 獲取每個月總天數 getAllDaysOfMonth(year,month) { return new Date(year,month,0).getDate(); }, // 獲取每個月第一天是星期幾 getFirstDayOfMonth(year,month) { return new Date(year, month - 1, 1).getDay(); }, // 計算本月前空了幾格 getEmptyGrids(year,month) { // FirstDayOfMonth表明本月的第一天是星期幾 const FirstDayOfMonth = this.getFirstDayOfMonth(year, month); let emptyGrids = []; // 有空格的狀況 if (FirstDayOfMonth > 0) { for (let i = 0; i < FirstDayOfMonth; i++) { emptyGrids.push({ 'num': '', 'fullDate': 'x' //x是我本身定義的一個值,表明沒有日期 }); } // 將空格放入數組 return emptyGrids; }else{ // 不然返回一個新數組 return []; } }, // 計算本月日曆 getDaysOfThisMonth(year,month) { let days = []; const AllDaysOfMonth = this.getAllDaysOfMonth(year, month); let fullMonth = month.toString().length === 1 ? `0${month}`:month; for (let i = 0; i < AllDaysOfMonth; i++) { let day = i+1, fullDay = day; fullDay = fullDay.toString().length === 1 ? `0${day}` : fullDay; days.push({ day, fullDay, 'fullDate': `${year}-${fullMonth}-${fullDay}` }); } // 返回每月的具體日期 return days; }, // 循環渲染日曆 // 從本月開始渲染,n表明包括本月開始連續渲染幾個月 fillCalendar(n) { let year = this.data.cur_year, month = this.data.cur_month, fullMonth, canlendar_data = []; // 計算年月以及具體日曆 for (let i = this.data.cur_month; i < this.data.cur_month + n; i++) { let EmptyGrids = this.getEmptyGrids(year, month); let DaysOfThisMonth = this.getDaysOfThisMonth(year, month); // 把空格和具體日曆合爲一個數組 let allDays = [...EmptyGrids, ...DaysOfThisMonth]; // 對年份和月份的計算作一些判斷 if (month > 12) { year++; month = 1; fullMonth = '01' canlendar_data.push({ year, month, fullMonth, allDays }); month++; }else{ fullMonth = month.toString().length === 1 ? `0${month}` : month; canlendar_data.push({ year, month, fullMonth, allDays }); month++; } } this.setData({ canlendar_data }) }, onLoad() { const date = new Date(); const cur_year = date.getFullYear(); const cur_month = date.getMonth() + 1; const cur_day = date.getDate(); this.setData({ date, cur_year, cur_month, cur_day }) let month = this.data.cur_month.toString().length === 1 ? `0${this.data.cur_month}` : this.data.cur_month; let day = this.data.cur_day.toString().length === 1 ? `0${this.data.cur_day}` : this.data.cur_day; let nowDate = `${cur_year}-${month}-${day}`; this.setData({ nowDate }) this.fillCalendar(6); }, // 點擊日期 chooseDate(e) { const year_click = e.currentTarget.dataset.year; const month_click = e.currentTarget.dataset.month; const day_click = e.currentTarget.dataset.day; console.log(year_click,month_click,day_click); // 若是是空格或者之前的日期就直接返回 if(day_click === ''||`${year_click}-${month_click}-${day_click}` < this.data.nowDate) { return; } // 獲取點擊對象的id let id = e.currentTarget.dataset.id; // data_click爲0表明選擇的是入住日期,不然就是離店日期 if (this.data.date_click == 0){ // 選擇入住日期 this.setData({ startDate: `${year_click}-${month_click}-${day_click}`, date_click: 1 }) }else { let newDay = new Date(Date.parse(id)); let oldDay = new Date(Date.parse(this.data.startDate)); // 判斷第二次點擊的日期在第一次點擊的日期前面仍是後面 if (newDay > oldDay) { this.setData({ endDate: `${year_click}-${month_click}-${day_click}`, date_click: 2 }) }else{ this.setData({ startDate: `${year_click}-${month_click}-${day_click}`, endDate: '', date_click: 1 }) } } } })
<!-- calendar.wxml文件 --> <view class="container"> <view id="week"> <view class="week-item {{idx===0||idx===6?'relax':''}}" wx:for="{{week_list}}" wx:for-index="idx">{{item}}</view> </view> <scroll-view scoll-y="true"> <view class="month-block" wx:for="{{canlendar_data}}" wx:for-item="canlendar_item"> <view class="month-title">{{canlendar_item.year}}年{{canlendar_item.month}}月</view> <view class="month-content"> <view class="month-day {{item.fullDate<nowDate?'gray':''}} {{startDate===item.fullDate?'startActive':''}} {{endDate===item.fullDate?'endActive':''}} {{item.fullDate>startDate&&item.fullDate<endDate&&startDate!==''&&endDate!==''?'midActive':''}}" bindtap="chooseDate" data-year="{{canlendar_item.year}}" data-month="{{canlendar_item.fullMonth}}" data-day="{{item.fullDay}}" data-id="{{item.fullDate}}" wx:for="{{canlendar_item.allDays}}">{{item.day}}</view> </view> </view> </scroll-view> </view>
{{idx===0||idx===6?'relax':''}} 是改變週六週日的顏色,
{{item.fullDate<nowDate?'gray':''}} 是改變過去日期的顏色,
{{startDate===item.fullDate?'startActive':''}} 判斷點擊的是入住日期,
{{endDate===item.fullDate?'endActive':''}} 判斷點擊的是離店日期,
{{item.fullDate>startDate&&item.fullDate<endDate&&startDate!==''&&endDate!==''?'midActive':''}} 改變入住日期和離店日期之間的日期顏色xml
到此一個簡單的日曆就完成了,固然這個日曆沒法知足全部業務需求,可是基本的日曆渲染功能以及點擊選擇功能都有。因此在業務需求之上對其進行小部分改變就能夠了,但願你們能夠留言指出個人問題,我也會進一步的改善這個日曆代碼。對象