需求:
小程序需要实现日历的需求,可以单选、可以选择区间、节假日和周六颜色高亮、返回本月。具体如图,类似猫眼app的日历选择。
思路:
- 参考市场上含有日历的小程序及app,确定是自己实现还是使用组件,骨朵使用的是Pikaday。
- 确定使用Vant Weapp组件库中日历。
- 需要对源码进行一些修改,首先样式的修改、包括顶部周日到周六、节假日及周六日日期的颜色、返回本月按钮的添加及样式。
- 前后实现了三种展示日历的不同方式
4-1. 第一种,根据官方示例引入日历组件,平铺整个页面。选择日期后会跳转返回列表页。
存在的问题:由于给日历的范围比较大,需要展示三年多的日期,导致渲染的时候比较慢,点进日历页后,页面会白屏1-2秒,整个日历才会显示出来。
4-2. 第二种,将引入日历的组件文件再作为组件,引入到列表页中,为了解决日历元素渲染久的问题,当日历页作为组件引入到列表页后,让它在列表页提前加载渲染,此时当点击选择日期的时候,日历已经渲染好了。
存在的问题:由于日历在列表页作为子组件,导致进来后一起渲染,列表页会白屏1-2秒,用户感受不好。决定给引入的日历组件加个变量控制其显示隐藏,给它个定时器,让其延迟加载,设置的时间短了,会中断echarts的渲染过程,echarts会等日历渲染完后,再继续渲染自己的图;设置的时间长了,进来之后点击选择日历没反应,可能还没渲染完。
4-3. 第三种,通过在列表页让日历以弹框的形式出来,直接将日历组件引入列表页。此时避免了列表页和日历页之间的频繁跳转导致路由堆积过多 。
存在的问题:虽然通过弹框加载,但日历渲染的时间还是需要1-2秒,如果日历和列表页一起渲染,会导致列表页白屏1-2秒,等到日历渲染完才会展示内容。如果给日历添加定时器让其延迟加载,等列表页渲染完后再去渲染日历,此时列表和图表正常加载,但由于日历没有加载完,选择日期不可点击,并且其他的按钮也不可点击,点击后会触发也会请求接口,但会等到日历渲染完毕才会将刚刚请求的新数据渲染到页面上。考虑给页面整个一个2秒的loading效果,页面可正常看到,2秒后,再让你其操作。
4-4. 第四种,日历通过弹框形式展现,在页面加载的时候给日历组件加上一个变量asyncLoad,控制其显示隐藏,写在onReady生命周期中,通过定时器给延迟50s,让变量变成true,此时列表一定渲染完成,echarts图可能渲染一半,不考虑图的渲染体验,等到日历组件渲染完成后继续加载图表。此时再去点击日期选择就可以使用了。以下实现步骤为该种方案 - 比较好的实现方式应该对这种需要渲染上千个数据的进行虚拟加载,这样就会避免了加载时间过长导致的种种问题。但由于使用的组件,暂时没有实现。
步骤:
-
修改样式及组件的属性配置
下图是下载好的组件库,删掉了没有用的组件
将日历中的日期进行三种展示,分别是,普通日期、节假日、周六日
添加返回本月按钮,以及返回本月对应的方法,在开发者工具上好用,但体验版上不好使
后续删掉了整个按钮,具体问题没有分析
-
修改样式及组件的属性配置
<!--pages/boxOfficeModule/boxOfficeList/boxOfficeList.wxml--> <view style="{ { !showCalendar ? 'badisplay:block' : 'background: #4c4c4c;display:none'}}" > <view>页面内容</view> <view class="dayDate"> <view class="pickerBox { {asyncShow ? 'open' : 'off'}}" bindtap="goCalendar" data-dateBox="{ {dateBox}}" data-platformIdIndex="{ {platformIdIndex}}"> <view class="picker">{ {dateName}}</view> <image class="drop-down" src="../../../images/drop-down.png"></image> </view> </view> </view> <view> <van-calendar wx:if="{ {asyncLoad}}" style="{ { showCalendar ? 'display:block' : 'display:none'}}" show-mark="{ { false }}" formatter="{ { formatter }}" default-date="{ { defaultVal }}" min-date="{ { minDate }}" max-date="{ { maxDate }}" show="{ { showCal }}" show-confirm="{ { false }}" bind:close="onClose" bind:confirm="onConfirm" round="false" position="bottom" /> </view>
// pages/boxOfficeModule/boxOfficeList/boxOfficeList.js var app = getApp() var util = require('../../../utils/util.js') import * as echarts from '../../../ec-canvas/echarts'; Page({ data: { date: '', showCal: false, minDate: new Date(2019, 0, 1).getTime(), maxDate: new Date().getTime(), defaultVal: new Date('2021-04-19').getTime(), formatter(day) { // console.log('day', day) const year = day.date.getFullYear() const month = day.date.getMonth() + 1 const date = day.date.getDate() let week = day.date.getDay() if (week === 0) week = 7 const holiday = [ { year: 2020, monthDate: [ { month: 1, date: [ { day: 1, text: '元旦', holidayColor: true }, { day: 24, text: '除夕', holidayColor: true }, { day: 25, text: '春节', holidayColor: true }, ] }, { month: 2, date: [ { day: 14, text: '情人节', holidayColor: true }, { day: 8, text: '元宵节', holidayColor: true } ] }, { month: 4, date: [ { day: 1, text: '愚人节', holidayColor: true }, { day: 4, text: '清明节', holidayColor: true } ] }, { month: 5, date: [ { day: 1, text: '劳动节', holidayColor: true } ] }, { month: 6, date: [ { day: 1, text: '儿童节', holidayColor: true }, { day: 25, text: '端午节', holidayColor: true } ] }, { month: 8, date: [ { day: 25, text: '七夕节', holidayColor: true } ] }, { mo