WeChat applet: handwriting calendar component

I. Introduction

Recently, the company is going to make a small program for hotel check-in. It is inevitable that the calendar will be used, and the small program has no built-in calendar component. I looked at the Internet and there was no calendar that was very suitable for my needs, so I wrote one myself.

Second, the code

1. Principle Analysis

There are only two things you need to know to write a calendar:

  1. How many days are there in a month;
  2. The first day of each month is the day of the week.

2. Functional analysis

Since it is a hotel check-in calendar, the following functions need to be implemented:

  1. Rendering calendar, generally starting from this month, to the calendar half a year later
  2. Past date is not selectable
  3. Click to get the check-in date, check-out date, and change the color of the corresponding date and the color of the entire time period

3. Data analysis

According to the final function implementation, the data structure of each month I generated is as follows:

{
    year: 2018,
    month: 3,
    fullMonth: '03',
    allDays:[
        {
            day: 1,
            fullDay: '01',
            fullDate: '2018-03-01'
        },
        {
            day: 2,
            fullDay: '02',
            fullDate: '2018-03-02'
        },
        //......
        //(后面的数据同上)
    ]
}

year is the year, month is the month, day is the date, and fullDate is the full date.
FullMonth and fullDay were originally two unnecessary data, but they were used when the date was clicked to change the color, because the applet did not provide a good filter to process the data. Of course, this problem is also related to my personal level. If there is a great god who has a better way, please leave a message to tell me. I really want to remove these two data.

4. Code analysis

// calendar.js文件

Page({
  data: {
    week_list: ['日','一','二','三','四','五','六'],
    startDate: '',
    endDate: '',
    date_click: 0
  },
  // 获取每月总天数
  getAllDaysOfMonth(year,month) {
    return new Date(year,month,0).getDate();
  },
  // 获取每月第一天是星期几
  getFirstDayOfMonth(year,month) {
    return new Date(year, month - 1, 1).getDay();
  },
  // 计算本月前空了几格
  getEmptyGrids(year,month) {
    // FirstDayOfMonth代表本月的第一天是星期几
    const FirstDayOfMonth = this.getFirstDayOfMonth(year, month);
    let emptyGrids = [];
    
    // 有空格的情况
    if (FirstDayOfMonth > 0) {
      for (let i = 0; i < FirstDayOfMonth; i++) {
        emptyGrids.push({
          'num': '',
          'fullDate': 'x'  //x是我自己定义的一个值,代表没有日期
        });
      }
      // 将空格放入数组
      return emptyGrids;
    }else{
      // 否则返回一个新数组
      return [];
    }
  },
  // 计算本月日历
  getDaysOfThisMonth(year,month) {
    let days = [];
    const AllDaysOfMonth = this.getAllDaysOfMonth(year, month);

    let fullMonth = month.toString().length === 1 ? `0${month}`:month;
    for (let i = 0; i < AllDaysOfMonth; i++) {
      let day = i+1,
          fullDay = day;

      fullDay = fullDay.toString().length === 1 ? `0${day}` : fullDay;
      days.push({
        day,
        fullDay,
        'fullDate': `${year}-${fullMonth}-${fullDay}`
      });
    }
    // 返回每个月的具体日期
    return days;
  },
  // 循环渲染日历
  // 从本月开始渲染,n代表包括本月开始连续渲染几个月
  fillCalendar(n) {
    let year = this.data.cur_year,
        month = this.data.cur_month,
        fullMonth,
        canlendar_data = [];

    // 计算年月以及具体日历
    for (let i = this.data.cur_month; i < this.data.cur_month + n; i++) {
      let EmptyGrids = this.getEmptyGrids(year, month);
      let DaysOfThisMonth = this.getDaysOfThisMonth(year, month);

      // 把空格和具体日历合为一个数组
      let allDays = [...EmptyGrids, ...DaysOfThisMonth];

      // 对年份和月份的计算做一些判断
      if (month > 12) {
        year++;
        month = 1;
        fullMonth = '01'
        canlendar_data.push({
          year, 
          month, 
          fullMonth,
          allDays });
        month++;
      }else{
        fullMonth = month.toString().length === 1 ? `0${month}` : month;
        canlendar_data.push({ 
          year, 
          month, 
          fullMonth,
          allDays });
        month++;
        
      }

    }

    this.setData({
      canlendar_data
    })
  },
  onLoad() {
    const date = new Date();
    const cur_year = date.getFullYear();
    const cur_month = date.getMonth() + 1;
    const cur_day = date.getDate();
    this.setData({
      date,
      cur_year,
      cur_month,
      cur_day
    })

    let month = this.data.cur_month.toString().length === 1 ? `0${this.data.cur_month}` : this.data.cur_month;
    let day = this.data.cur_day.toString().length === 1 ? `0${this.data.cur_day}` : this.data.cur_day;
    let nowDate = `${cur_year}-${month}-${day}`;

    this.setData({
      nowDate
    })

    this.fillCalendar(6);
  },
  // 点击日期
  chooseDate(e) {
    const year_click = e.currentTarget.dataset.year;
    const month_click = e.currentTarget.dataset.month;
    const day_click = e.currentTarget.dataset.day;
    console.log(year_click,month_click,day_click);
    // 如果是空格或者以前的日期就直接返回
    if(day_click === ''||`${year_click}-${month_click}-${day_click}` < this.data.nowDate) {
      return;
    }

    // 获取点击对象的id
    let id = e.currentTarget.dataset.id;
    
    // data_click为0代表选择的是入住日期,否则就是离店日期
    if (this.data.date_click == 0){
      // 选择入住日期
      this.setData({
        startDate: `${year_click}-${month_click}-${day_click}`,
        date_click: 1
      })
    }else {
      let newDay = new Date(Date.parse(id));
      let oldDay = new Date(Date.parse(this.data.startDate));

      // 判断第二次点击的日期在第一次点击的日期前面还是后面
      if (newDay > oldDay) {
        this.setData({
          endDate: `${year_click}-${month_click}-${day_click}`,
          date_click: 2
        })
      }else{
        this.setData({
          startDate: `${year_click}-${month_click}-${day_click}`,
          endDate: '',
          date_click: 1
        })
      }
    }
  }
})
<!-- calendar.wxml文件 -->

<view class="container">
  <view id="week">
    <view class="week-item {{idx===0||idx===6?'relax':''}}" wx:for="{{week_list}}" wx:for-index="idx">{{item}}</view>
  </view>
  <scroll-view scoll-y="true">
    <view class="month-block" wx:for="{{canlendar_data}}" wx:for-item="canlendar_item">
      <view class="month-title">{{canlendar_item.year}}年{{canlendar_item.month}}月</view>
      <view class="month-content">
        <view class="month-day {{item.fullDate<nowDate?'gray':''}} {{startDate===item.fullDate?'startActive':''}} {{endDate===item.fullDate?'endActive':''}} {{item.fullDate>startDate&&item.fullDate<endDate&&startDate!==''&&endDate!==''?'midActive':''}}" bindtap="chooseDate" data-year="{{canlendar_item.year}}" data-month="{{canlendar_item.fullMonth}}" data-day="{{item.fullDay}}" data-id="{{item.fullDate}}" wx:for="{{canlendar_item.allDays}}">{{item.day}}</view>
      </view>
    </view>
  </scroll-view>
</view>

{{idx === 0 || idx === 6? 'relax': ''}} is to change the color of Saturday and Sunday,
{{item.fullDate <nowDate? 'gray': ''}} is to change The color of the past date,
{{startDate === item.fullDate? 'StartActive': ''}} judges that the clicked date is the check-in date,
{{endDate === item.fullDate? 'EndActive': ''}} judges the click Is the departure date,
{{item.fullDate> startDate && item.fullDate <endDate && startDate! == '' && endDate! == ''? 'MidActive': ''}} change the date color between the check-in date and the check-out date

4. Conclusion

At this point, a simple calendar is completed. Of course, this calendar cannot meet all business needs, but the basic calendar rendering function and click selection function are available. Therefore, a small part of it can be changed on the basis of business requirements. I hope you can leave a message to point out my problem, and I will further improve this calendar code.

Guess you like

Origin www.cnblogs.com/10manongit/p/12722340.html