用vue 编写一个日历组件

一个日历有的是42天有的是35天,原因是6行或7行,7行展示的就比较全面;42天的优点是能全部展示出上个月,当前月以及下个月,缺点是上个月和下个月占比较多,有些冗余,如果是35天看起来就会比较精简,但有的月份就不能全部展示出来还是需要42天,这个也无伤大雅,我们就以42天为例。

首先我们需要看当前月的第一天是周几,5月的1号就是周三,那么就用42 - 2(这里注意如果是周日在第一个就是42 - 周几,如果是周一在第一个就是42 - (周几 - 1 )剩下的就是当前月和下个月的日期了。

我创建一个公共js里面放一些公共的方法方便在组件中调用;公共的js我就叫utils.js;
getYearMonthDay 就是utils里面的一个公共方法,是为了方便获取年月日;
const getYearMonthDay =  (date) => {
 let year = date.getFullYear();
 let month = date.getMonth();
 let day = date.getDate();
 return {year, month, day};
};

computed: {
    visibleCalendar: function () {
        let calendatArr = [];
        先得到当前的年,月,日
        let {year, month, day} = utils.getNewDate(utils.getDate(this.time.year, this.time.month, 1));
        
        获取当月的第一天 得到2019-5-1
        let currentFirstDay = utils.getDate(year, month, 1);
        
        获取第一天是星期几 得到 3
        let weekDay = currentFirstDay.getDay();
        
        用当月的第一天减去 周几前面几天 这样就能得到上个月开始的天数 (当前月1号是周三,那么周一就是上个月的最后两天)
        let startTime = currentFirstDay - (weekDay - 1) * 24 * 60 * 60 * 1000;
        
        然后得到所有的日期
        for (let i = 0; i < 42; i++) {
          calendatArr.push({
            date: new Date(startTime + i * 24 * 60 * 60 * 1000), 
            year:new Date(startTime + i * 24 * 60 * 60 * 1000). getFullYear(), 
            month: new Date(startTime + i * 24 * 60 * 60 * 1000).getMonth() + 1, 
            day: new Date(startTime + i * 24 * 60 * 60 * 1000).getDate() 
          })
        };
        return calendatArr
    }
}

然后dom结构去v-for这个数组,这样就能得到一个初始的日历了

但是这样很丑,而且不能区分出哪一天是上个月哪一天是下个月,所以我们需要给上下月去加一下样式来区分当前月和上下月的区分

<ul class="calendar-view clear">
  <li v-for="(item, index) in visibleCalendar" 
    :key="index" 
    class="date-view"
    :class="[
      {'notCurrentMonth-class': !isCurrentMonth(item.date)},
      {currentDay: isCurrentDay(item.date)},
    ]"
    @click="handleClickDay(item, index)"
  >
    <span class="date-day" >
      {{item.day}}
    </span>
  </li>
</ul>
notCurrentMonth-class 是区分上下月的类名
currentDay 是判断是否是今天的类名

判断是否是当前月的方法,传入每一天 用传入的每一天去和当前年月做比较然后返回
isCurrentMonth (date) {
    let {year: currentYear, month: currentMonth} = utils.getYearMonthDay(utils.getDate(this.time.year, this.time.month, 1));
    let {year, month} = utils.getYearMonthDay(date);
    return currentYear == year && currentMonth == month
}
判断是否是当前天的方法 同理
isCurrentDay (date) {
    let {year: currentYear, month: currentMonth, day: currentDay} = utils.getYearMonthDay(new Date());
    let {year, month, day} = utils.getYearMonthDay(date);
    return currentYear == year && currentMonth == month && currentDay == day;
}

现在就差左右切换和点击今天回到当前月了,接下来就很简单,我们先写两个方法用来切换上下月

先去utils里面创建一个新的方法用来获取当前几月几日
const getDate = (year, month, day) => {
  return new Date(year, month, day);
}
在data () {
    let {year, month, day} = utils.getYearMonthDay(new Date());
    return {
        yearMonth: {year, month, day}, 
    }
}
// 上一个月 获取当年月 用setMonth()去设置月份,然后更新yearMonth
  handlePrevMonth () {
    let prevMonth = utils.getDate(this.yearMonth.year,this.yearMonth.month,1);
    prevMonth.setMonth(prevMonth.getMonth() - 1);
    this.yearMonth = utils.getYearMonthDay(prevMonth);
  }
  // 下一个月 获取当年月 用setMonth()去设置月份,然后更新yearMonth
  handleNextMonth () {
    let nextMonth = utils.getDate(this.yearMonth.year,this.yearMonth.month,1); 
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    this.yearMonth = utils.getYearMonthDay(nextMonth);
  }
  // 点击回到今天 同理
  handleToday () {
    this.yearMonth = utils.getYearMonthDay(new Date());
  }

 就这样一个左右切换以及点击回到今天的日历就完成了

发布了93 篇原创文章 · 获赞 93 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_41937388/article/details/103260165