因为解决不了vant日历组件动态渲染formatter的问题,于是自己撸了一个简易的小程序日历组件

  • A+
所属分类:Web前端
摘要

 代码仓库地址:https://github.com/imxiaoer/WeChatMiniCalendar 一、效果图如下:

 

代码仓库地址:https://github.com/imxiaoer/WeChatMiniCalendar

 

一、效果图如下:

 

因为解决不了vant日历组件动态渲染formatter的问题,于是自己撸了一个简易的小程序日历组件

 

二、业务场景介绍

客户原始需求:用户需要知道在选中的月份中,哪些日期是有客户预约的,并且显示当天预约人数,点击有预约的日期则进入预约信息详细页,详细页内可以新建预约;点击没有预约的日期则直接进入新建预约页面。

 

三、需求实现

因为项目用的是vant的小程序ui组件,所以刚开始想的是用vant的日历组件来实现此需求。经过几番尝试后,始终实现不了 formatter 的动态数据渲染,最后放弃了(如有大佬已实现此功能,麻烦留言分享下你的解决方案,谢谢),然后自己写了一个日历组件。

 

主要功能:

1.  根据传入的日期,渲染当月日历,如传入 2021/6/1,则渲染2021年6月份的日历

2. 点击单个日期,返回具体年月日,并且被点击日期变色

3. 根据用户数据,动态渲染日历标注。传入的日期变更,或者是用户数据变更,都会重新渲染日历及标注。上面效果图下方的【改日期】和 【改数据】就是用来测试这个功能的。

 

 

四、主要代码

 

1.  calendar.wxml

<view class="calendar-box">   <view class="head-box">     <view class="title-box">{{title}}</view>     <view class="week-box">       <view class="week-item"></view>       <view class="week-item"></view>       <view class="week-item"></view>       <view class="week-item"></view>       <view class="week-item"></view>       <view class="week-item"></view>       <view class="week-item"></view>     </view>   </view>   <view class="date-box">     <view       bindtap="clickItem"       data-date="{{day.date}}"       class="date-item {{currentDate == day.date ? 'active' : ''}}"       wx:for="{{daysArray}}" wx:for-item="day"       wx:key="index">       <view class="top-text" wx:if="{{day.topText}}">{{day.topText}}</view>       {{day.date}}       <view class="bottom-text" wx:if="{{day.bottomText}}">{{day.bottomText}}</view>     </view>   </view> </view>

 

2. calendar.js

// components/calendar/calendar.js Component({   /**    * 组件的属性列表    */   properties: {     defaultDate: {       type: String,       observer () {         this.getCurrentDaysAndWeekStart();         this.renderDate();         this.triggerEvent('formatter', this.data.daysArray);       }     },     isDataChange: {       type: Boolean,       value: false,       observer () {         this.triggerEvent('formatter', this.data.daysArray);       }     },     daysData: {       type: Array,       observer (newVal) {         if (newVal.length > 0) {           this.setData({ daysArray: newVal });         }       }     }   },    /**    * 组件的初始数据    */   data: {     Y: '', //     M: '', //     D: '', //     W: '', // 星期     firstDayWeek: '', // 当前月第一天星期几     lastDayWeek: '',  // 当前月最后一天星期几     daysCount: 0,  // 总天数     daysArray: [], // 日历中天数数组     title: '',     currentDate: '0'   },    /**    * 组件的方法列表    */   methods: {     // 获取当前月的天数,以及当前月第一天是星期几,最后一天是星期几     getCurrentDaysAndWeekStart () {       let dateString = this.properties.defaultDate;       let today = new Date();       if (dateString) {         today = new Date(dateString);       }       let Y = today.getFullYear();       let M = today.getMonth() + 1;       let D = today.getDate();       let daysCount = new Date(Y, M, 0).getDate(); // 当前月最后一天日期,即当前月的天数       let firstDayWeek = new Date(Y, M - 1, 1).getDay(); // 第一天星期几       let lastDayWeek = new Date(Y, M, 0).getDay(); // 最后一天星期几       this.setData({         Y: Y,         M: M,         D: D,         firstDayWeek: firstDayWeek,         lastDayWeek: lastDayWeek,         daysCount: daysCount,         title: `${Y}年${M}月`       });     },      // 根据总天数和第一天星期几,最后一天星期几,渲染日历天数数组     renderDate () {       let firstDayWeek = this.data.firstDayWeek;       let lastDayWeek = this.data.lastDayWeek;       let daysCount = this.data.daysCount;       let days = []; // 当前月总天数数组       for (let i = 1; i <= daysCount; i++) {         days.push({           date: i.toString(),           topText: '',           bottomText: ''         });       }              // 补全前面 (因为一周七天,如果第一天是星期三,则需要把星期一和星期二数据补全)       for (let i = 0; i < firstDayWeek; i++) {         days.unshift({           date: '',           topText: '',           bottomText: ''         });       }              // 补全后面 (因为一周七天,如果最后一天是星期五,则需要把星期六和星期天数据补全)       for (let i = lastDayWeek; i <= 7; i++) {         days.push({           date: '',           topText: '',           bottomText: ''         });       }        this.setData({ daysArray: days });     },      // 点击单个日期事件     clickItem (event) {       let date = event.currentTarget.dataset.date;       if (date) {         this.setData({ currentDate: date });         this.triggerEvent('select', `${this.data.Y}-${this.data.M}-${date}`);       }     }   } })

 

 

3. calendar.wxss

/* components/calendar/calendar.wxss */ .calendar-box {   background-color: #ffffff;   padding: 10rpx;   color: #323233; } .head-box {   box-shadow: 0 2px 10px rgb(125 126 128 / 16%); } .title-box {   padding: 20rpx 0 40rpx 0;   text-align: center;   font-size: 14px; } .week-box {   display: flex;   justify-content: space-between;   font-size: 12px;   padding-bottom: 20rpx; } .week-item {   width: 100%;   text-align: center; } .date-box {   display: flex;   flex-wrap: wrap;   justify-content: space-between; } .date-item {   display: flex;   flex-direction: column;   align-items: center;   justify-content: center;   height: 125rpx;   width: 14.285%;   border-radius: 10rpx;   font-size: 12px; } .top-text, .bottom-text {   font-size: 8px;   color: red; } .active {   background-color: pink; }

 

因为网络的原因,打不开github,所以暂时没法上传demo代码,之后代码上传到GitHub了会在文章顶部贴出地址,谢谢关注。

 

因为解决不了vant日历组件动态渲染formatter的问题,于是自己撸了一个简易的小程序日历组件