一、媒介
近来公司要做一个旅店入住的小顺序,不可避免的肯定会使用到日历,而小顺序没有内置的日历组件。在网上看了一下也没有异常合适需求的日历,因而本身写了一个。
二、代码
1. 道理剖析
写一个日历只须要知道两件事变:
- 一个月有若干天;
- 每个月的第一天是礼拜几。
2. 功用剖析
由因而旅店入住的日历,所以须要完成以下功用:
- 衬着日历,平常是从本月最先,到半年以后的日历
- 过去的日期不可选
- 完成点击猎取入住日期、退房日期,以及转变响应日期的色彩和全部时间段的色彩
3. 数据剖析
依据末了的功用完成,我天生的每个月的数据结构以下:
{
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。固然这个题目也和我的个人程度有关,如果有哪位大神有更好的要领,请留言告诉我。我异常想去掉这两个数据。
4.代码剖析
// 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’:”}} 转变入住日期和离店日期之间的日期色彩
四、结语
到此一个简朴的日历就完成了,固然这个日历没法满足一切营业需求,然则基础的日历衬着功用以及点击挑选功用都有。所以在营业需求之上对其举行小部分转变就能够了,愿望人人能够留言指出我的题目,我也会进一步的改良这个日历代码。