通过下面截图能够看出
- 点击上月和下月切换月份
- 点击具体的日期能够在页面上显示选中日期
- 点击确定将会取得选中日期
- 点击灰色的日期能够跳转对应月份并高亮日期
构造
日历构造次要分为 mask 和 calender
-
代码
<view class="mask {{show ?'show':''}}"catch:tap="onClickMask"></view> <view class="calender {{onceShow ?'show':''}} {{show ? 'enter' : 'leave'}}"> <view class="header"> <view class="header-title"> <view catch:tap="onToggleMonthClick" data-type="prev"> 上月 </view> <view class="title">{{year}}年 {{month+1}} 月 </view> <view catch:tap="onToggleMonthClick" data-type="next"> 下月 </view> </view> <!-- 星期 --> <view class="weekdays"> <view class="weekday"> 日 </view> <view class="weekday"> 一 </view> <view class="weekday"> 二 </view> <view class="weekday"> 三 </view> <view class="weekday"> 四 </view> <view class="weekday"> 五 </view> <view class="weekday"> 六 </view> </view> </view> <view class="body"> <view class="month"> <!-- 日期 --> <view class="dates"> <block wx:for="{{thisMonthDates}}" wx:key="*this"> <view class="date {{item.isToday ?'today':''}} {{item.isSelectedDate ? 'selected-date' : ''}} {{item.isEmptyDate ?'empty-date':''}}"data-index="{{index}}"data-type="{{item.monthState}}"data-formatDate="{{item.formatDate}}"catch:tap="onSelectDateClick" >{{item.date}} </view> </block> </view> </view> <view class="footer"> 确定 </view> </view> </view>
mask 是遮罩层,当日历弹出时,显示在日历前面,calender 之所以没有放在外面,是因为组件弹出时须要做动画,组件显示的时候 mask 须要立刻呈现。
calender 分为有两种操作
- 上月和下月切换
- 日期点击高亮
依据日历构造,写出日历款式
- 日期的款式分为以后月、上月、下月,上月下月为灰色
- 高亮当天
- 切换日期时,当天的色彩是金色
- 款式代码
外围代码
日历组件最重要的是如何计算当月多少天,以及对应星期几。
好在 js 提供了 new Date().getDate() 能够获取明天是几号,Date 可承受 3 个参数 year、month、date,如果 date 大于这个月的最大天数,就会主动换算成下个月的几号,同理如何小于 1 号,就会主动换算出上个月的几号。利用这个个性,date 传递 0 进去就能晓得有多少天了。
new Date(2020, 5, 2).getDate() // 2
new Date(2020, 5, 1).getDate() // 1
new Date(2020, 5, 0).getDate() // 31
通过 new Date().getDay() 能够获取 date 是星期几,它的值是 0~6,正好能够用 0 代表星期日。
-
代码
getThisDateWeek({year, month, date}: YearMonthDate) {return new Date(Date.UTC(year, month, date)).getDay()}, getThisMonthDays(year: number, month: number) {return new Date(year, month + 1, 0).getDate()}
晓得了当月多少天,怎么晓得当月后面和前面有多少天呢?
-
代码
methods: { // 当月 createDays() {const thisMonthDates: any[] = [] const {year, month} = this.data const thisMonthTotalDate = this.getThisMonthDays(year, month) for (let date = 1; date <= thisMonthTotalDate; date++) {const monthGrid = this.formatMonthGrid({year, month, date}) thisMonthDates.push(monthGrid) } this.data.thisMonthDates = thisMonthDates this.setData({thisMonthTotalDate}) }, // 单月的上月和下月有多少天 createEmptyDays() {let {year, month, thisMonthDates} = this.data // 当月第一天是星期几 const firstDayWeek = this.getThisDateWeek({year, month, date: 1}) const emptyGridsBefore = this.getBeforeMonthEmpty(firstDayWeek) const emptyGridsAfter = this.getAfterMonthEmpty(firstDayWeek) thisMonthDates = [...emptyGridsBefore, ...thisMonthDates, ...emptyGridsAfter] this.setData({thisMonthDates}) }, // 上月 getBeforeMonthEmpty(firstDayWeek: number) {const {year, month} = this.data const emptyGridsBefore: any[] = [] const {prevYear, prevMonth} = this.prevYear(year, month) const prevMonthDay = this.getThisMonthDays(year, prevMonth) // 上月 补满 1 号后面的日期 for (let i = 1; i <= firstDayWeek; i++) {const date = prevMonthDay - (firstDayWeek - i) const monthGrid = this.formatMonthGrid({year: prevYear, month: prevMonth, date}, MonthState.Prev) emptyGridsBefore.push(monthGrid) } return emptyGridsBefore }, // 下月 getAfterMonthEmpty(firstDayWeek: number) {const emptyGridsAfter: any[] = [] const {thisMonthTotalDate, year, month} = this.data const {nextYear, nextMonth} = this.nextYear(year, month) // 日期默认显示 42 天,-7 是为了如果 35 天能显示全的话就用 35 天 const nextMonthDay = 42 - thisMonthTotalDate - firstDayWeek - 7 >= 0 ? 42 - thisMonthTotalDate - firstDayWeek - 7 : 42 - thisMonthTotalDate - firstDayWeek // 下月补满当月最初一天前面的日期 for (let date = 1; date <= nextMonthDay; date++) {const monthGrid = this.formatMonthGrid({year: nextYear, month: nextMonth, date}, MonthState.Next) emptyGridsAfter.push(monthGrid) } return emptyGridsAfter }, // 如果是 1 月,上月就是上年 12 月 prevYear(year: number, month: number) { const prevYear = month === 0 ? year - 1 : year const prevMonth = month === 0 ? 11 : month - 1 return {prevYear, prevMonth} }, // 如果是 12 月,下月就是下年 1 月 nextYear(year: number, month: number) { const nextYear = month === 11 ? year + 1 : year const nextMonth = month === 11 ? 0 : month + 1 return {nextYear, nextMonth} }, }
性能代码
-
代码
methods: { // state 是用来判断上月还是下月 formatMonthGrid({year, month, date}: YearMonthDate, state?: string) {const formatDate = this.formatDate({year, month, date}) const isSelectedDate = this.defaultSelectedDateGrid(formatDate, state) const isEmptyDate = this.isEmptyDateGrid(month) const week = this.getThisDateWeek({year, month, date}) const isToday = this.isToday(formatDate) return { year, month, date, formatDate, week, isSelectedDate, isEmptyDate, isToday, monthState: state } }, // 点击日期高亮 setSelectedDateGrid(formatDate: string) {const {thisMonthDates} = this.data let selectedDate: string = '' thisMonthDates.forEach((thisMonthDate: any) => {if (thisMonthDate.formatDate === formatDate) { thisMonthDate.isSelectedDate = true selectedDate = thisMonthDate.formatDate } else {thisMonthDate.isSelectedDate = false} }) this.data.selectedDate = selectedDate this.setData({thisMonthDates}) }, // 默认日期高亮 defaultSelectedDateGrid(formatDate: string, state: string) {const {selectedDate} = this.data // 只高亮当月,上月和下月的不高亮 return formatDate === selectedDate && !state }, // 明天 isToday(formatDate: string) {const {value} = this.data return value === formatDate }, // 是不是当月 isEmptyDateGrid(month: number) {const {month: thisMonth} = this.data return month !== thisMonth }, formatDate({year, month, date}: YearMonthDate) {return `${year}-${month + 1}-${date}` }, }
事件
-
代码
methods: {onSelectDateClick(e: Event) {const {formatdate, type} = e.currentTarget.dataset const {selectedDate} = this.data if (formatdate === selectedDate) return this.toggleMonth(type) this.setSelectedDateGrid(formatdate) }, // 上月和下月切换 onToggleMonthClick(e: Event) {const {type} = e.currentTarget.dataset this.toggleMonth(type) }, toggleMonth(type: string) {if (type === MonthState.Prev) {this.prevMonth() } else if (type === MonthState.Next) {this.nextMonth() } }, prevMonth() {const {year, month} = this.data const {prevYear, prevMonth} = this.prevYear(year, month) this.setData({year: prevYear, month: prevMonth}, () => {this.createDays() this.createEmptyDays()}) }, nextMonth() {const {year, month} = this.data const {nextYear, nextMonth} = this.nextYear(year, month) this.setData({year: nextYear, month: nextMonth}, () => {this.createDays() this.createEmptyDays()}) }, }
Properties
-
代码
properties = { show: { type: Boolean, value: false, observer(show: boolean) {if (show) this.setData({enter: show, onceShow: true}) } }, value: { type: String, value: '-1', observer(value: string) { // 2020-6-15 const year = +(value.split("-")[0]) const month = +(value.split("-")[1]) - 1 const date = +(value.split("-")[2]) this.data.selectedDate = value this.setData({year, month, date}, () => {this.initDate() this.createDays() this.createEmptyDays()}) } } }, methods = {initDate() {let {year, month, date} = this.data if (year && month && date) return year = new Date().getFullYear() month = new Date().getMonth() date = new Date().getDate() this.data.selectedDate = this.formatDate({year, month, date}) this.setData({year, month, date}) }, onClickMask() {this.setData({show: false, value: '-1'}) }, }