基于 Dayjs 與 Vue2 的簡易日歷

/**
日歷原始數(shù)據(jù)結(jié)構(gòu)
months: [
['第1周', 1, 2, 3, 4, 5, 6, 7],
['第2周', 8, 9, 10, 11, 12, 13, 14],
['第3周', 15, 16, 17, 18, 19, 20, 21],
],
*/
<template>
  <div class="Calendar">
    <table class="width100p">
      <caption class="lineHeight30" style="color: #2c3e50">{{ formatDate(firstDay) }}</caption>
      <tbody>
        <tr class="tableClass border1cccccc">
          <th class="lineHeight30">教學(xué)周</th>
          <th class="lineHeight30">星期一</th>
          <th class="lineHeight30">星期二</th>
          <th class="lineHeight30">星期三</th>
          <th class="lineHeight30">星期四</th>
          <th class="lineHeight30">星期五</th>
          <th class="lineHeight30">星期六</th>
          <th class="lineHeight30">星期日</th>
        </tr>
        <template v-for="(week, index) in calendarData">
          <tr :key="'w'+index" class="tableClass border1cccccc">
            <td v-for="(atom, index) in week" :key="'d'+index">
              <div>{{ atom.label }}</div>

            </td>
          </tr>
        </template>
      </tbody>
    </table>
    <br>
    <button @click="doBeforeOneMonth">上一月</button>
    <button @click="doAfterOneMonth">下一月</button>
  </div>
</template>

<script>
import dayjs from 'dayjs'

export default {
  name: 'zydxCalendar', // 組件名稱
  components: {},
  props: [], // 組件參數(shù)
  model: { // 用于 props 綁定父級 v-model
  },
  filters: { // 過濾器
  },
  computed: { // 計算屬性
  },
  watch: { // 監(jiān)聽屬性
  },
  data () {
    return {
      /*
      * 頁面狀態(tài)
      * */

      /*
      * 頁面數(shù)據(jù)
      * */
      calendarData: [],
      firstDay: '2021-1-1'
    }
  },
  methods: {
    // 格式化時間
    formatDate (date) {
      return dayjs(date).format('YYYY年M月')
    },
    // 上一月
    doBeforeOneMonth () {
      this.firstDay = this.beforeOneMonth(this.firstDay)
      this.getCalendar(this.firstDay)
    },
    beforeOneMonth (date) {
      // date 格式 2021-1-1
      return dayjs(date).subtract(1, 'month').format('YYYY-M-D')
    },
    // 下一月
    doAfterOneMonth () {
      this.firstDay = this.afterOneMonth(this.firstDay)
      this.getCalendar(this.firstDay)
    },
    afterOneMonth (date) {
      // date 格式 2021-1-1
      return dayjs(date).add(1, 'month').format('YYYY-M-D')
    },
    // 渲染日歷
    getCalendar (firstDay) {
      // firstDay 格式 2021-1-1
      const day = parseInt(dayjs(firstDay).format('D')) // 獲取 日
      const yearMonth = dayjs(firstDay).format('YYYY-M')
      let firstDayOfWeek = dayjs(firstDay).day() // 當天是星期幾
      const totalDays = dayjs(firstDay).daysInMonth() // 這個月一共有幾天
      const remainDays = totalDays - day // 這個月還剩幾天
      const days = [] // 當前月的所有號
      // 生成當月日期數(shù)組
      let i = -1
      while (i < remainDays) {
        days.push(day + i + 1)
        i++
      }
      // 月的數(shù)組
      let finalMonth = []
      let sliceStart = 0 // 截取日期的起始
      if (firstDayOfWeek === 0) {
        firstDayOfWeek = 7
      }
      let sliceGap = 7 - firstDayOfWeek + 1 // 截取幾天
      let isArrayEmpty = false // 是否截取不出來了的標記
      let sliceTimes = 0
      while (!isArrayEmpty) {
        let weekTip = [] // 日歷中每一條的數(shù)據(jù)
        if (sliceTimes === 0) { // 首次截取
          let weekTipAfter = days.slice(sliceStart, sliceGap)
          if (weekTipAfter.length < 7) {
            for (let i = 0; i < 7 - weekTipAfter.length; i++) { // 添加前面的空白
              weekTip.push('')
            }
          }
          weekTip = weekTip.concat(weekTipAfter)
        } else { // 再次截取
          weekTip = days.slice(sliceGap, sliceGap + 7)
          sliceGap = sliceGap + 7
          // 尾部添 空白
          let trailAppend = 7 - weekTip.length
          if (trailAppend < 7 && trailAppend > 0) {
            for (let j = 0; j < trailAppend; j++) {
              weekTip.push('')
            }
          }
          trailAppend = 0
        }
        sliceTimes++
        // 如果截取不出來了則 跳出循環(huán)
        if (weekTip.length !== 0) {
          finalMonth.push(weekTip)
        } else {
          isArrayEmpty = true
        }
      }

      // 添加教學(xué)周
      finalMonth.map((item, index) => {
        item.splice(0, 0, `第 ${index + 1} 周`)
      })

      // 更換數(shù)據(jù)結(jié)構(gòu)
      let calendarData = []
      finalMonth.map((item) => {
        let calendarPart = []
        item.map((atom) => {
          if (typeof (atom) === 'number') {
            calendarPart.push({
              label: atom,
              date: yearMonth + '-' + atom,
              remarks: [] // 此處可以放一些數(shù)據(jù)
            })
          } else {
            calendarPart.push({
              label: atom
            })
          }
        })
        calendarData.push(calendarPart)
      })

      // 調(diào)試輸出
      // console.log(day + '日當天是星期幾', firstDayOfWeek)
      // console.log('這個月一共有幾天: ', totalDays)
      // console.log('這個月還剩幾天: ', remainDays)
      // console.log('days數(shù)組', days)
      // console.log('獲得最終日歷', finalMonth)
      // console.log('日歷數(shù)據(jù)結(jié)構(gòu)調(diào)整', calendarData)
      // 結(jié)束
      this.calendarData = calendarData
    }
  },
  beforeCreate () { // 播放加載動畫
  },
  created () { // 結(jié)束加載動畫, 發(fā)起異步請求
  },
  mounted () { // DOM構(gòu)建完成, 即將顯示頁面
    this.getCalendar(this.firstDay)
  },
  updated () { // view重新渲染, 數(shù)據(jù)更新
  },
  beforeDestroy () { // 組件實例銷毀之前
  }
}
</script>

<style scoped>
.lineHeight30 {
  line-height: 30px;
}
caption {
  padding: 0 0 0 30px;
  border: 1px #cccccc solid;
  border-bottom: none;
}
.tableClass th {
  border: 1px #cccccc solid;
  font-size: 14px;
}
.tableClass td {
  border: 1px #cccccc solid;
  font-size: 14px;
}
</style>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容