点击翻页按钮,根据回调进来的event对象来获取元素上的data-*属性,然后调用changeDate这个方法来更新日历数据,这个方法接收一个Date对象,代表要翻页后的日期。
暂且不关心changeDate具体干了些什么,看看.body.row里有一个循环,每一个元素都绑定了dateClickEvent事件,而且每一个元素都附带了自己所属的年份、月份和天数信息,这些信息是非常有用的,当点击了具体的某一天,可以通过获取元素上的data-*信息来知道我们具体选择的日期。除此之外,元素上的class属性包裹了一长串的判断表达式。这些语句最终的目的是为了给元素动态变更,.old代表当前的日期不是本月日期,因为每一版的日期除了当前月份的日期还可能包含上一月和下一月的部分日期,我们给予它灰色的样式显示,.current代表今天的日期,用实心填充颜色的背景样式修饰,.active即代表着当前选中的日期。
dateClickEvent事件其实也是调用了changeDate事件,本质上也是也是改变日期,额外的工作就是保存选中的日期到selected对象中。
dateClickEvent(e) { const {year, month, date} = e.currentTarget.dataset; const {data} = this.data; let selectDateText = ''; data['selected']['year'] = year; data['selected']['month'] = month; data['selected']['date'] = date; this.setData({ data: data }); changeDate.call(this, new Date(year, parseInt(month) - 1, date)); }
来看看重中之重的changeDate函数,这个函数的代码比较多,虽然堆砌大量在一个函数中是个不好的习惯,不过里面声明变量和赋值比较多,业务代码比较少:
/** * 变更日期数据 * @param {Date} targetDate 当前日期对象 */ function changeDate(targetDate) { let date = targetDate || new Date(); let currentDateObj = new Date(); let showMonth, //当天显示月份 showYear, //当前显示年份 showDay, //当前显示星期 showDate, //当前显示第几天 showMonthFirstDateDay, //当前显示月份第一天的星期 showMonthLastDateDay, //当前显示月份最后一天的星期 showMonthDateCount; //当前月份的总天数 let data = []; showDate = date.getDate(); showMonth = date.getMonth() + 1; showYear = date.getFullYear(); showDay = date.getDay(); showMonthDateCount = new Date(showYear, showMonth, 0).getDate(); date.setDate(1); showMonthFirstDateDay = date.getDay(); //当前显示月份第一天的星期 date.setDate(showMonthDateCount); showMonthLastDateDay = date.getDay(); //当前显示月份最后一天的星期 let beforeDayCount = 0, beforeYear, //上页月年份 beforMonth, //上页月份 afterYear, //下页年份 afterMonth, //下页月份 afterDayCount = 0, //上页显示天数 beforeMonthDayCount = 0; //上页月份总天数 //上一个月月份 beforMonth = showMonth === 1 ? 12 : showMonth - 1; //上一个月年份 beforeYear = showMonth === 1 ? showYear - 1 : showYear; //下个月月份 afterMonth = showMonth === 12 ? 1 : showMonth + 1; //下个月年份 afterYear = showMonth === 12 ? showYear + 1 : showYear; //获取上一页的显示天数 if (showMonthFirstDateDay != 0) beforeDayCount = showMonthFirstDateDay - 1; else beforeDayCount = 6; //获取下页的显示天数 if (showMonthLastDateDay != 0) afterDayCount = 7 - showMonthLastDateDay; else showMonthLastDateDay = 0; //如果天数不够6行,则补充完整 let tDay = showMonthDateCount + beforeDayCount + afterDayCount; if (tDay <= 35) afterDayCount += (42 - tDay); //6行7列 = 42 //虽然翻页了,但是保存用户选中的日期信息是非常有必要的 let selected = this.data.data['selected'] || { year: showYear, month: showMonth, date: showDate }; let selectDateText = selected.year + '年' + formatNumber(selected.month) + '月' + formatNumber(selected.date) + '日'; data = { currentDate: currentDateObj.getDate(), //当天日期第几天 currentYear: currentDateObj.getFullYear(), //当天年份 currentDay: currentDateObj.getDay(), //当天星期 currentMonth: currentDateObj.getMonth() + 1, //当天月份 showMonth: showMonth, //当前显示月份 showDate: showDate, //当前显示月份的第几天 showYear: showYear, //当前显示月份的年份 beforeYear: beforeYear, //当前页上一页的年份 beforMonth: beforMonth, //当前页上一页的月份 afterYear: afterYear, //当前页下一页的年份 afterMonth: afterMonth, //当前页下一页的月份 selected: selected, selectDateText: selectDateText }; let dates = []; let _id = 0; //为wx:key指定 //上一月的日期 if (beforeDayCount > 0) { beforeMonthDayCount = new Date(beforeYear, beforMonth, 0).getDate(); for (let fIdx = 0; fIdx < beforeDayCount; fIdx++) { dates.unshift({ _id: _id, year: beforeYear, month: beforMonth, date: beforeMonthDayCount - fIdx }); _id++; } } //当前月份的日期 for (let cIdx = 1; cIdx <= showMonthDateCount; cIdx++) { dates.push({ _id: _id, active: (selected['year'] == showYear && selected['month'] == showMonth && selected['date'] == cIdx), //选中状态判断 year: showYear, month: showMonth, date: cIdx }); _id++; } //下一月的日期 if (afterDayCount > 0) { for (let lIdx = 1; lIdx <= afterDayCount; lIdx++) { dates.push({ _id: _id, year: afterYear, month: afterMonth, date: lIdx }); _id++; } } data.dates = dates; this.setData({ data: data, pickerDateValue: showYear + '-' + showMonth }); loadItemListData.call(this); }
虽然这段这段代码有点啰嗦,不过总结下来无非就是获取当前月的信息,上一页的信息和下一页的信息,这些信息包括具体的年月日和星期。
年月选择Picker