VUE篇之日历组件

1.简单日历组件展示

思路:根据当前月的第一天是星期几,来显示日期

<template>
  <div class="wrap">
    <el-button @click="preMonth">上个月</el-button>
    <el-tag>当前年份{{ curYear }}</el-tag>
    <el-tag>当前月份{{ curMonth }}</el-tag>
    <el-button @click="nextMonth">下个月</el-button>
    <div class="weeks">
      <div v-for="item in week" :key="item" class="week">{{ item }}</div>
    </div>
    <div class="days">
      <!-- 当月 -->
      <div v-for="item in curDays" :key="item + 'cur'" class="curday">{{ item }}</div>
    </div>
  </div>
</template>
<script>
import moment from 'moment';
moment.suppressDeprecationWarnings = true;
export default {
  data() {
    return {
      curYear: moment().year(), //当前年
      curMonth: moment().month() + 1, //当前月
      week: ['一', '二', '三', '四', '五', '六', '七'],
      firstDay: moment(`${moment().year()}-${moment().month() + 1}`)
        .startOf('month')
        .day(), //获取当月第一天是星期几;星期日为 0,星期六为 6
      curDays: moment().daysInMonth() //获取当月一共有多少天
    };
  },

  methods: {
    preMonth() {
      this.curMonth--;
      // 如果小于1表示上一年;重置日期
      if (this.curMonth < 1) {
        this.curYear--;
        this.curMonth = 12;
      }
      this.curDays = moment(`${this.curYear}-${this.curMonth}`).daysInMonth();
      this.firstDay = moment(`${this.curYear}-${this.curMonth}`).startOf('month').day();
      if (this.firstDay == 0) {
        this.firstDay = 7;
      }
    },
    nextMonth() {
      this.curMonth++;
      // 如果超过12表示下一年;重置日期
      if (this.curMonth > 12) {
        this.curYear++;
        this.curMonth = 1;
      }
      this.curDays = moment(`${this.curYear}-${this.curMonth}`).daysInMonth();
      this.firstDay = moment(`${this.curYear}-${this.curMonth}`).startOf('month').day();
      if (this.firstDay == 0) {
        this.firstDay = 7;
      }
    }
  }
};
</script>

<style lang="scss">
.wrap {
  width: 700px;
  height: 100%;
  .weeks {
    width: 100%;
    height: 50px;
    display: flex;
    .week {
      width: 100px;
      line-height: 50px;
      text-align: center;
      background: gainsboro;
    }
  }
  .days {
    display: flex;
    flex-wrap: wrap;
    .lastday,
    .curday {
      width: 100px;
      line-height: 50px;
      text-align: center;
    }
    .lastday {
      color: gold;
    }
  }
}
</style>

2.日历组件增强版------带有上个月或者下个月日期

较比上一版本,这个版本多了2个方法,主要用于更新上个月剩余日期,以及下个月最新日期

上个月日期:
// 获取上个月剩余天数
    getPreMonthDays() {
      if (this.firstDay == 1) return; //表示上个月无剩余天数
      let month = this.curMonth;
      let year = this.curYear;
      month--;
      if (month == 0) {
        year--;
        month = 12;
      }
      // 获取上个月的天数
      const days = moment(`${year}-${month}`).daysInMonth();
      this.preDays = days;
    },
 下个月日期:
// 获取下个月要显示的天数
    getNextMonthDays() {
      let month = this.curMonth;
      let year = this.curYear;
      // 获取当月最后一天是星期几
      const lastDay = moment(`${year}-${month}`).endOf('month').day();
      this.nextDays = lastDay == 0 ? 7 : lastDay;
    }

 整体代码:

<template>
  <div class="wrap">
    <el-button @click="preMonth">上个月</el-button>
    <el-tag>当前年份{{ curYear }}</el-tag>
    <el-tag>当前月份{{ curMonth }}</el-tag>
    <el-button @click="nextMonth">下个月</el-button>
    <div class="weeks">
      <div v-for="item in week" :key="item" class="week">{{ item }}</div>
    </div>
    <div class="days">
      <!-- 上个月 -->
      <div v-for="item in firstDay - 1" :key="item + 'pre'" class="lastday">
        {{ preDays - (firstDay - 1 - item) }}
      </div>
      <!-- 当月 -->
      <div v-for="item in curDays" :key="item + 'cur'" class="curday">{{ item }}</div>
      <!-- 下个月 -->
      <div v-for="item in 7 - nextDays" :key="item + 'next'" class="lastday">
        {{ item }}
      </div>
    </div>
  </div>
</template>
<script>
import moment from 'moment';
moment.suppressDeprecationWarnings = true;
export default {
  data() {
    return {
      preDays: 30,
      nextDays: 7,
      curYear: moment().year(), //当前年
      curMonth: moment().month() + 1, //当前月
      week: ['一', '二', '三', '四', '五', '六', '七'],
      firstDay: moment(`${moment().year()}-${moment().month() + 1}`)
        .startOf('month')
        .day(), //获取当月第一天是星期几;星期日为 0,星期六为 6
      curDays: moment().daysInMonth() //获取当月一共有多少天
    };
  },
  mounted() {
    this.getPreMonthDays();
    this.getNextMonthDays();
  },
  methods: {
    preMonth() {
      this.curMonth--;
      // 如果小于1表示上一年;重置日期
      if (this.curMonth < 1) {
        this.curYear--;
        this.curMonth = 12;
      }
      this.curDays = moment(`${this.curYear}-${this.curMonth}`).daysInMonth();
      this.firstDay = moment(`${this.curYear}-${this.curMonth}`).startOf('month').day();
      if (this.firstDay == 0) {
        this.firstDay = 7;
      }
      // 显示上个月日期
      this.getPreMonthDays();
      this.getNextMonthDays();
    },
    nextMonth() {
      this.curMonth++;
      // 如果超过12表示下一年;重置日期
      if (this.curMonth > 12) {
        this.curYear++;
        this.curMonth = 1;
      }
      this.curDays = moment(`${this.curYear}-${this.curMonth}`).daysInMonth();
      this.firstDay = moment(`${this.curYear}-${this.curMonth}`).startOf('month').day();
      if (this.firstDay == 0) {
        this.firstDay = 7;
      }
      // 显示上个月日期
      this.getPreMonthDays();
      this.getNextMonthDays();
    },
    // 获取上个月剩余天数
    getPreMonthDays() {
      if (this.firstDay == 1) return; //表示上个月无剩余天数
      let month = this.curMonth;
      let year = this.curYear;
      month--;
      if (month == 0) {
        year--;
        month = 12;
      }
      // 获取上个月的天数
      const days = moment(`${year}-${month}`).daysInMonth();
      this.preDays = days;
    },
    // 获取下个月要显示的天数
    getNextMonthDays() {
      let month = this.curMonth;
      let year = this.curYear;
      // 获取当月最后一天是星期几
      const lastDay = moment(`${year}-${month}`).endOf('month').day();
      this.nextDays = lastDay == 0 ? 7 : lastDay;
    }
  }
};
</script>

<style lang="scss">
.wrap {
  width: 700px;
  height: 100%;
  .weeks {
    width: 100%;
    height: 50px;
    display: flex;
    .week {
      width: 100px;
      line-height: 50px;
      text-align: center;
      background: gainsboro;
    }
  }
  .days {
    display: flex;
    flex-wrap: wrap;
    .lastday,
    .curday {
      width: 100px;
      line-height: 50px;
      text-align: center;
    }
    .lastday {
      color: gold;
    }
  }
}
</style>

3.日历组件增强版------可选择区间日期

思路:通过clickCount记录点击区间次数,默认是0,点击第一次是1,第二次是2;如果clickCount==2重置clickCount=0

页面渲染:通过判断日期是否在选择区间的最大和最小之间,来更改背景色

相比较之前,更新的代码:

方法新增一个点击事件

selectDate(year, day) {
      this.clickCount++;
      const date = new Date(`${year}-${this.curMonth}-${day}`);
      if (this.clickCount == 1) {
        this.startTime = date;
      } else if (this.clickCount == 2) {
        this.endTime = date;
        this.clickCount = 0;
      }
      if (this.endTime && +this.startTime > +this.endTime) {
        [this.startTime, this.endTime] = [this.endTime, this.startTime];
      }
      // console.log(
      //   this.clickCount,
      //   moment(this.startTime).format('YYYY-MM-DD'),
      //   moment(this.endTime).format('YYYY-MM-DD')
      // );
    }
  computed: {
    isSelected() {
      return (year, day) => {
        const date = new Date(`${year}-${this.curMonth}-${day}`);
        return (
          (+this.startTime <= +date && +this.endTime >= +date) || +date == +this.startTime || +date == +this.endTime
        );
      };
    }
  },

整体代码:

<template>
  <div class="wrap">
    <el-button @click="preMonth">上个月</el-button>
    <el-tag>当前年份{{ curYear }}</el-tag>
    <el-tag>当前月份{{ curMonth }}</el-tag>
    <el-button @click="nextMonth">下个月</el-button>
    <div class="weeks">
      <div v-for="item in week" :key="item" class="week">{{ item }}</div>
    </div>
    <div class="days">
      <!-- 上个月 -->
      <div
        v-for="item in firstDay - 1"
        :key="item + 'pre'"
        :class="['lastday', { select: isSelected(curYear - 1, preDays - (firstDay - 1 - item)) }]"
        @click="selectDate(curYear - 1, preDays - (firstDay - 1 - item))"
      >
        {{ preDays - (firstDay - 1 - item) }}
      </div>
      <!-- 当月 -->
      <div
        v-for="item in curDays"
        :key="item + 'cur'"
        :class="['curday', { select: isSelected(curYear, item) }]"
        @click="selectDate(curYear, item)"
      >
        {{ item }}
      </div>
      <!-- 下个月 -->
      <div
        v-for="item in 7 - nextDays"
        :key="item + 'next'"
        :class="['lastday', { select: isSelected(curYear + 1, item) }]"
        @click="selectDate(curYear + 1, item)"
      >
        {{ item }}
      </div>
    </div>
  </div>
</template>
<script>
import moment from 'moment';
moment.suppressDeprecationWarnings = true;
export default {
  data() {
    return {
      startTime: null, //记录区间开始时间
      endTime: null, //记录区间结束时间
      clickCount: 0, //用于记录点击次数
      preDays: 30, //上个月天数
      nextDays: 7, //下个月天数
      curYear: moment().year(), //当前年
      curMonth: moment().month() + 1, //当前月
      week: ['一', '二', '三', '四', '五', '六', '七'],
      firstDay: moment(`${moment().year()}-${moment().month() + 1}`)
        .startOf('month')
        .day(), //获取当月第一天是星期几;星期日为 0,星期六为 6
      curDays: moment().daysInMonth() //获取当月一共有多少天
    };
  },
  computed: {
    isSelected() {
      return (year, day) => {
        const date = new Date(`${year}-${this.curMonth}-${day}`);
        return (
          (+this.startTime <= +date && +this.endTime >= +date) || +date == +this.startTime || +date == +this.endTime
        );
      };
    }
  },
  mounted() {
    this.getPreMonthDays();
    this.getNextMonthDays();
  },
  methods: {
    preMonth() {
      this.curMonth--;
      // 如果小于1表示上一年;重置日期
      if (this.curMonth < 1) {
        this.curYear--;
        this.curMonth = 12;
      }
      this.curDays = moment(`${this.curYear}-${this.curMonth}`).daysInMonth();
      this.firstDay = moment(`${this.curYear}-${this.curMonth}`).startOf('month').day();
      if (this.firstDay == 0) {
        this.firstDay = 7;
      }
      // 显示上个月日期
      this.getPreMonthDays();
      this.getNextMonthDays();
    },
    nextMonth() {
      this.curMonth++;
      // 如果超过12表示下一年;重置日期
      if (this.curMonth > 12) {
        this.curYear++;
        this.curMonth = 1;
      }
      this.curDays = moment(`${this.curYear}-${this.curMonth}`).daysInMonth();
      this.firstDay = moment(`${this.curYear}-${this.curMonth}`).startOf('month').day();
      if (this.firstDay == 0) {
        this.firstDay = 7;
      }
      // 显示上个月日期
      this.getPreMonthDays();
      this.getNextMonthDays();
    },
    // 获取上个月剩余天数
    getPreMonthDays() {
      if (this.firstDay == 1) return; //表示上个月无剩余天数
      let month = this.curMonth;
      let year = this.curYear;
      month--;
      if (month == 0) {
        year--;
        month = 12;
      }
      // 获取上个月的天数
      const days = moment(`${year}-${month}`).daysInMonth();
      this.preDays = days;
    },
    // 获取下个月要显示的天数
    getNextMonthDays() {
      let month = this.curMonth;
      let year = this.curYear;
      // 获取当月最后一天是星期几
      const lastDay = moment(`${year}-${month}`).endOf('month').day();
      this.nextDays = lastDay == 0 ? 7 : lastDay;
    },
    selectDate(year, day) {
      this.clickCount++;
      const date = new Date(`${year}-${this.curMonth}-${day}`);
      if (this.clickCount == 1) {
        this.startTime = date;
      } else if (this.clickCount == 2) {
        this.endTime = date;
        this.clickCount = 0;
      }
      if (this.endTime && +this.startTime > +this.endTime) {
        [this.startTime, this.endTime] = [this.endTime, this.startTime];
      }
      // console.log(
      //   this.clickCount,
      //   moment(this.startTime).format('YYYY-MM-DD'),
      //   moment(this.endTime).format('YYYY-MM-DD')
      // );
    }
  }
};
</script>

<style lang="scss">
.wrap {
  width: 700px;
  height: 100%;
  .weeks {
    width: 100%;
    height: 50px;
    display: flex;
    .week {
      width: 100px;
      line-height: 50px;
      text-align: center;
      background: gainsboro;
    }
  }
  .days {
    display: flex;
    flex-wrap: wrap;
    .lastday,
    .curday {
      width: 100px;
      line-height: 50px;
      text-align: center;
      cursor: pointer;
    }
    .lastday {
      color: gold;
    }
    .select {
      background: pink;
      color: #fff;
    }
  }
}
</style>

4.日历组件增强版------可自定义日期内容

未完待续