日历组件

31 阅读2分钟

开发一个uniapp日历组件

时间数据类型常用知识点

const date = new Date()

date.getFullYear()// 年
date.getMonth() // 月, 值范围[0,11]
date.getDate() // 日 值范围[1, 31]
date.getDay() // 星期几 值范围[0,6] 0是周日, 1-6周一到周六
date.setDate(12) // 设置时间日期
date.setFullYear(date.getFullYear(), date.getMonth(), 0)// 获取上个月最后一天时间
<template>
  <view class="calendar">
    <view class="bar">
      <view class="bar-left">
        <u-icon name="play-left-fill" color="#00B1FF" @click="monthChange(-1)"></u-icon>
      </view>
      <view class="bar-cont">{{ barCont }}</view>
      <view class="bar-right" @click="monthChange(1)">
        <u-icon name="play-right-fill" color="#00B1FF"></u-icon>
      </view>
    </view>
    <view class="header-wrap">
      <view class="header-item" v-for="(iv, i) in weekDays" :key="i">{{ iv }}</view>
    </view>
    <view class="calenday-wrap" v-for="(week, ind) in weeks" :key="ind">
      <view class="calenday-item" v-for="(item, index) in week" :key="index" :class="[item.isShow ? 'is-now-month' : '']">
        {{ item.value ? new Date(item.value).getDate() : "" }}
      </view>
    </view>
  </view>
</template>

<script>
import dayjs from "dayjs";
export default {
  data() {
    return {
      weeks: [[]],
      weekDays: ["日", "一", "二", "三", "四", "五", "六"],
      currentDate: new Date(),
    };
  },
  props: {},
  computed: {
    barCont() {
      let month = new Date(this.currentDate).getMonth() + 1;
      return `${new Date(this.currentDate).getFullYear()}年${month > 9 ? month : "0" + month}月`;
    },
  },
  watch: {
    currentDate: {
      handler(value) {
        this.getWeeks(value);
      },
      immediate: true,
      deep: true,
    },
  },
  created() {},
  methods: {
    monthChange(index) {
      this.currentDate = new Date(new Date(this.currentDate).setMonth(this.currentDate.getMonth() + index));
      this.getWeeks(this.currentDate);
    },

    getWeeks(date = new Date("2023-09-09")) {
      this.weeks = [[]];
      date = new Date(date);
      let firstDate = new Date(date.getFullYear(), date.getMonth(), 1);
      let firstDay = new Date(firstDate).getDay();
      let lastDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
      let preMonthDates = new Date(date.getFullYear(), date.getMonth(), 0);

      let weekIndex = 0;

      // 获取第一列
      for (let i = firstDay; i--; i >= 0) {
        this.weeks[weekIndex].push({
          value: new Date(new Date(date.getFullYear(), date.getMonth() - 1).setDate(preMonthDates.getDate() - i)),
        });
      }
      let currentDate = new Date(firstDate);
      while (currentDate <= lastDate) {
        let data = {
          value: dayjs(currentDate).format("YYYY-MM-DD"),
          isShow: true,
        };
        if (currentDate.getDay() == 0) {
          weekIndex++;
          this.weeks[weekIndex] = [data];
        } else {
          this.weeks[weekIndex].push(data);
        }

        currentDate.setDate(currentDate.getDate() + 1);
      }

      // 填充下一个月日期
      let lastWeek = this.weeks[this.weeks.length - 1];
      let lastWeekDate = new Date(lastWeek[lastWeek.length - 1].value);
      let lastWeekDay = lastWeekDate.getDay();

      if (this.weeks.length == 6) {
        for (let i = 1; i <= 6 - lastWeekDay; i++) {
          this.weeks[this.weeks.length - 1].push({
            value: dayjs(new Date(date.getDate(), date.getMonth() + 1, i)).format("YYYY-MM-DD"),
          });
        }
      } else if (this.weeks.length == 5) {
        let lastDate = "";
        for (let i = 1; i <= 6 - lastWeekDay; i++) {
          lastDate = new Date(date.getDate(), date.getMonth() + 1, i);
          this.weeks[this.weeks.length - 1].push({
            value: dayjs(new Date(date.getDate(), date.getMonth() + 1, i)).format("YYYY-MM-DD"),
          });
        }
        let lastweeks = [];
        if (!lastDate) {
          lastDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
        }
        for (let i = 0; i < 7; i++) {
          lastweeks.push({
            value: dayjs(lastDate.setDate(lastDate.getDate() + 1)).format("YYYY-MM-DD"),
          });
        }
        this.weeks.push(lastweeks);
      }
    },
  },
};
</script>
<style lang="scss">
@mixin flex-center($col: center, $row: center, $dir: row) {
  display: flex;
  flex-direction: $dir;
  justify-content: $col;
  align-items: $row;
}

.calendar {
  width: 690rpx;
  height: 694rpx;
  background: #ffffff;
  border-radius: 24rpx;
  padding: 20rpx;
  .header-wrap {
    @include flex-center(flex-start, center);
    .header-item {
      color: #999999;
      font-size: 24rpx;
      flex: 1;
      height: 78rpx;
      @include flex-center(center, center);
    }
  }

  .calenday-wrap {
    @include flex-center(flex-start, center);
    .calenday-item {
      font-size: 24rpx;
      flex: 1;
      height: 78rpx;
      color: #999;
      @include flex-center(center, center);
    }

    .is-now-month {
      color: #333;
      font-weight: 600;
    }
  }

  .bar {
    height: 100rpx;
    @include flex-center();
    .bar-cont {
      margin: 0 30rpx;
    }
  }
}
</style>