纯手敲日历组件(vue)

1,080 阅读2分钟

日历组件

先看效果图,如下:在线预览

背景介绍:pc端需求,做一个日历组件,可以在上面添加日程。当然这里业务功能部分就没有写,大家只可参考日历的实现即可。

核心代码介绍

根据vue的核心思想:数据驱动来生成所需要的数据,实现页面的自动渲染及更新。

  • 组装日期核心对象calendarData 看到这个图,第一个想到的是要生成每个月的所有天数,然后还有各个状态:
即默认当天日期(图中默认蓝色数字)、选中日期(点击背景蓝色)、不可选的日期(灰色字体)及(有日程的等)及样式。
  • 生成日期对象:
 // 初始化日历
 // isClickToday参数只是为了处理点击“今天”的判断
    initCalendar(isClickToday = false) {
      const nowDate = new Date()
      this.viewDate(nowDate, isClickToday)
    },
    // 初始化日期控件
    viewDate(nowDate, isClickToday = false) {
      this.currentShowDate = Utility.formatDate(nowDate, 'yyyyMMdd')
      const year = nowDate.getFullYear()
      const month = nowDate.getMonth() + 1
      const currentDate = nowDate.getDate()
      this.currentYear = year
      this.currentMonth = month
      let dayNum = 0 // 当前月有多少天
      if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
        dayNum = 31
      } else if (month === 4 || month === 6 || month === 9 || month === 11) {
        dayNum = 30
      } else if (month === 2 && this.isLeapYear(year)) { // 如果是闰年,2月有29天
        dayNum = 29
      } else {
        dayNum = 28
      }
      this.calendarData = []
      var _firstDay = new Date(year, month - 1, 1) // 当前月第一天
      for (var i = 0; i < 42; i++) {
        let day = i + 1 - _firstDay.getDay() // 根据周几计算
        let _thisDate = new Date(year, month - 1, day)
        let _thisMonth = _thisDate.getMonth() + 1
        let _thisDay = _thisDate.getDate()
        let _currentDate = Utility.formatDate(_thisDate, 'yyyy-MM-dd')
        let curentDay = {
          isCurrentMonth: _thisMonth === month, // 是否是当月时间,只有当月才可以点击和移动变色
          isCurrentDay: _thisDay === currentDate, // 是否是当月的当天
          isClick: false,
          value: _thisDay,
          month: _thisMonth,
          longStrDate: _currentDate.replace(/-/g, ''),
          currentDate: _currentDate,
          isHasData: false // 是否存在数据(处理业务逻辑时用)
        }
        this.calendarData.push(curentDay)
      }
      if (isClickToday) {
        let item = this.calendarData.find(d => d.isCurrentDay)
        this.$emit('changeDate', item.currentDate)
      }
    },
    // 判断是否为闰年
    isLeapYear(year) {
      if ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0)) {
        return true
      } else {
        return false
      }
    },
    // 切换日期
    changeMonth(type) {
      let nowDate = new Date()
      let month = this.currentMonth
      if (type === 0) {
        month = this.currentMonth - 1
      } else {
        month = this.currentMonth + 1
      }
      nowDate.setFullYear(this.currentYear)
      nowDate.setMonth(month - 1)
      nowDate.setDate(nowDate.getDate())
      console.log('切换日期', nowDate)
      this.viewDate(nowDate)
      // 回调方法
      this.$emit('changeDate', Utility.formatDate(nowDate, 'yyyy-MM-dd'))
    },
    // 选中哪一天
    checkDate(item) {
      if (!item.isCurrentMonth) return
      this.calendarData.forEach(d => {
        //  && !item.isCurrentDay 如果当天就不选中
        d.isClick = d.value === item.value && d.month === item.month
      })
      // 回调方法
      this.$emit('checkDay', item)
    },
    // 赋值具体日期
    checkDays(date) {
      this.viewDate(new Date(date))
    }
  • 组件的使用:/views/calendar.vue
 <cale-comp ref="calendar" @changeDate="changeDate" @checkDay="checkDay"></cale-comp>

详细代码可参考这里.