小程序日历代码实现逻辑

小程序日历代码实现逻辑

由于项目中使用到日历功能,考虑到后期维护及扩展的问题,自己手写了一个日历组件,解决目前项目中遇到的问题的同时,方便以后公司有需要用到的时候可以随时扩展和修改

日历样式

小程序日历代码实现逻辑_第1张图片
date.png

性能分析

目前只是在开发者工具上初步测试了一下,并未发现比较耗性能的代码,只是颜色搭配比较乱
小程序日历代码实现逻辑_第2张图片
audits.png

逻辑分析

1、获取当前月份的天数,并得到本月的第一天是从周几开始的, 最后一天是从周几开始的
2、获取上月需要在本月展示的天数(即本月第一天是周几)
3、获取下月需要在本月展示的天数(即7-本月最后一天是周几)
总结:
    从上面的逻辑中可以看到,很重要的一个点就是, 本月的第一天和本月的最后一天,从这个天数可以获取到本月前后两个月在本月展示的效果的 

核心代码1-获取当月需要在页面上展示的天数

    /**
     * 加载当前月的天
     */
    loadCurrentMonthDays(y, m) {
      let currentDate = new Date(y, m, 0); //当前日期
      let year = currentDate.getFullYear(); // 得到年份
      let month = currentDate.getMonth() + 1;   // 得到月份
      let week = currentDate.getDay();       // 得到周几 (0: 周日 1: 周一 2: 周二 ...)
      let day = currentDate.getDate();       // 今天几号
      let daysLength = this.currentMonthDays(year, month); // 当前月份总共有多少天
      month = month < 10 ? "0" + month : month

      let nowDay = new Date();
      let nowY = nowDay.getFullYear();
      let nowM = nowDay.getMonth() + 1;
      nowM = nowM < 10 ? "0" + nowM : nowM;
      let nowD = nowDay.getDate();

      let tempCurrentMonthDays = [];
      for (let i = 1; i <= daysLength; i++) {
        let date = i < 10 ? "0" + i : i;
        let temp = {
          year: year,
          month: month,
          day: date,
          fullID: `${year}${month}${date}`,
          isCurrentDay: `${nowY}${nowM}${nowD}` === `${year}${month}${date}` ? true : false, //是否是今天
          isPointDay: this.data.selectDays.includes(`${year}${month}${date}`)
        };
        tempCurrentMonthDays.push(temp);
        //初始化选中今天
        if (temp.isCurrentDay && !this.data.activeDate) {
          this.setData({
            activeDate: temp
          })
          this.onChange(this.data.activeDate);
        }

      }
      return tempCurrentMonthDays;
    }

核心代码2-获取上月需要在页面上展示的天数

    /**
     * 获取上个月对应的日期
     */
    loadLastMonthDays(y, m) {
      let currentDate = new Date(y, m, 0); //当前日期
      let year = currentDate.getFullYear(); // 得到年份
      let month = currentDate.getMonth();   // 得到月份
      let week = currentDate.getDay();       // 得到周几 (0: 周日 1: 周一 2: 周二 ...)

      //获取本月第一天周几
      let firstDate = new Date(`${year}/${month + 1}/01`);
      week = firstDate.getDay();       // 得到周几 (0: 周日 1: 周一 2: 周二 ...)


      let lastMonth = month;
      let lastYear = year;
      if (lastMonth == 0) {
        lastYear = lastYear - 1;
        lastMonth = 12;
      }

      //上月日期
      let lastDate = new Date(year, month, 0);
      let date = lastDate.getDate(); //上个月总共多少天

      lastMonth = lastMonth < 10 ? "0" + lastMonth : lastMonth;
      let tempMonthDays = [];
      for (let i = date - week + 1; i <= date; i++) {
        let date = i < 10 ? "0" + i : i;
        tempMonthDays.push({
          year: lastYear,
          month: lastMonth,
          day: date,
          fullID: `${lastYear}${lastMonth}${date}`,
          isPointDay: this.data.selectDays.includes(`${lastYear}${lastMonth}${date}`)
        })
      }
      return tempMonthDays;
    }

核心代码3-获取下月需要在页面上展示的天数

    /**
     * 获取下个月对应的日期
     */
    loadNextMonthDays(y, m) {
      let currentDate = new Date(y, m, 0); //当前日期
      let year = currentDate.getFullYear(); // 得到年份
      let month = currentDate.getMonth() + 1;   // 得到月份
      let date = currentDate.getDate();     // 获取本月天数

      //获取本月最后一天周几
      let endDate = new Date(`${year}/${month}/${date}`);
      let week = endDate.getDay();       // 得到周几 (0: 周日 1: 周一 2: 周二 ...)

      let nextMonth = month + 1;
      let nextYear = year;
      //下个月日期
      if (nextMonth == 13) {
        nextYear = nextYear + 1;
        nextMonth = 1;
      }
      nextMonth = nextMonth < 10 ? "0" + nextMonth : nextMonth;
      let tempMonthDays = [];
      for (let i = 0; i < (7 - week - 1); i++) {
        let date = i + 1;
        date = date < 10 ? "0" + date : date;
        tempMonthDays.push({
          year: nextYear,
          month: nextMonth,
          day: date,
          fullID: `${nextYear}${nextMonth}${date}`,
          isPointDay: this.data.selectDays.includes(`${nextYear}${nextMonth}${date}`)
        })
      }
      return tempMonthDays;
    }

核心代码4-调用三个函数赋值

    /**
     * 加载当前月份日历
     */
    loadCurrentMonth(type = "") {
      let currentDate = (() => {
        if (Object.keys(this.data.currentMonth).length === 0) {
          return new Date();
        }
        return new Date(this.data.currentMonth.year, this.data.currentMonth.month, 0);
      })(); //当前日期

      let year = currentDate.getFullYear(); // 当前展示的年份
      let month = currentDate.getMonth() + 1;   // 当前展示的月份
      if ("last" === type) {
        month = month - 1;
        if (month == 0) {
          year = year - 1;
          month = 12;
        }
      } else if ("next" === type) {
        month = month + 1;
        if (month == 13) {
          year = year + 1;
          month = 1;
        }
      }
      month = month < 10 ? '0' + month : month;
      this.setData({
        currentMonth: { year, month }, // 当前展示的月份
        lastMonthDay: this.loadLastMonthDays(year, month),
        currentMonthDay: this.loadCurrentMonthDays(year, month),
        nextMonthDay: this.loadNextMonthDays(year, month)
      })
    },

页面布局

在代码中定义了三个时间对象的数组,分别是上月天的对象数组,本月天的对象数组,下月天的对象数组,将这三个数组在页面上分别循环出来即达到上面图中展示的效果

注意

1、需要注意的点是在使用 new Date()的时候传入日期,需要使用 / 去分割,因为可能部分iPhone的机型不识别 - 的分割
2、可能有其他的实现日历的逻辑,此代码仅供参考

你可能感兴趣的:(小程序日历代码实现逻辑)