zoukankan      html  css  js  c++  java
  • 一个简易的小程序日历组件

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

    一、效果图如下:

    二、业务场景介绍

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

    三、需求实现

    因为项目用的是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;
    }
  • 相关阅读:
    bzoj2733: [HNOI2012]永无乡
    bzoj3141: [Hnoi2013]旅行
    bzoj3144: [Hnoi2013]切糕
    bzoj3140: [Hnoi2013]消毒
    bzoj3139: [Hnoi2013]比赛
    bzoj3142: [Hnoi2013]数列
    bzoj3572: [Hnoi2014]世界树
    bzoj2286: [Sdoi2011]消耗战
    bzoj3611: [Heoi2014]大工程
    The Unsolvable Problem
  • 原文地址:https://www.cnblogs.com/similar/p/14833872.html
Copyright © 2011-2022 走看看