1.はじめに
最近、ホテルのチェックイン用の小さなプログラムを作成する予定ですが、カレンダーを使うことは避けられず、小さなプログラムにはカレンダーコンポーネントが組み込まれていません。インターネットを見て、自分のニーズにぴったりのカレンダーがなかったので、自分で書きました。
第二に、コード
1.原理分析
カレンダーを書くために知っておくべきことが2つだけあります。
- 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'
},
//......
//(后面的数据同上)
]
}
年は年、月は月、日は日付、fullDateは完全な日付です。
FullMonthとfullDayは元々2つの不要なデータでしたが、データを処理するための適切なフィルターがアプレットになかったため、日付をクリックして色を変更したときに使用されました。もちろん、この問題は私の個人的なレベルにも関係しているので、より良い方法を持つ偉大な神がいたら、メッセージを残して教えてください。これら2つのデータを本当に削除したい。
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': ''}}チェックイン日とチェックアウト日の間の日付の色を変更しますか
4.まとめ
この時点で単純なカレンダーが完成しますが、もちろんこのカレンダーはすべてのビジネスニーズを満たすことはできませんが、基本的なカレンダーレンダリング機能とクリック選択機能は利用できます。したがって、ビジネス要件に基づいてその一部を変更できます。メッセージを残して私の問題を指摘していただければ幸いです。このカレンダーコードをさらに改善します。