关于vue.js:用vue来写一个日历组件

39次阅读

共计 4242 个字符,预计需要花费 11 分钟才能阅读完成。

我的项目要用到一个日历, 然而 css 和性能比拟奇怪, 就须要本人撸一个了

原理
一个日历以后月页面会显示 3 局部的日期天数
上月的,本月的,下月的
计算到这 3 局部组合起来的数组就是残缺的当月日历
所以重点在于计算这三局部就实现了

1. 上月的
new Date('2021-09-01').getDay()
2021 年 9 月 1 号是星期 3, 这时候就失去上月的 3 天
2. 本月的
new Date(year, month, 0).getDate()
3. 下月的
7 - (preAndCenter.length % 7)

最初失去当前页所以日期数组后就能够随便扩大本人要的性能了

<template>
  <div class="calendar_mod">
    <div class="header_warp">
        <div class="header_btn" @click="monthSwitch('prev')"> 上 </div>
        <div class="header_center">{{headerData.year}} / {{headerData.month}}</div>
        <div class="header_btn" @click="monthSwitch('next')"> 下 </div>
    </div>
    <div class="week_warp">
      <div class="week_item" v-for='(item,index) in weeks' :key='index'>{{item}}</div>
    </div>
    <div class="cell_warp">
      <div class="cell_box" v-for='(item,index) in allDays' :key='index'>
          <div :class="compDayClass(item)" >{{item.num}}</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "my-calendar",
  props:{
      marks:{
          type:Array,
          default:()=>{return []
          }
      }
  },
  data() {
    return {headerData: {},
      weeks: ["日", "一", "二", "三", "四", "五", "六"],
      allDays: [],
      preMonthDay: [], // 上月 day 数组};
  },
  
  created() {this.headerData = this.getCurrentDate();  // 获取以后年月
    this.allDays = this.computer(this.headerData.year,this.headerData.month)
    
    this.$watch(()=>{this.getMark(this.marks,this.headerData.year,this.headerData.month)
    })
  },
  computed:{compDayClass(){return function(item){return `${item.type} ${item.mark?'marking':''}`
          }
      },
  },
  methods: {
    // 计算方法汇总
    computer(year,month){let cMonthWeek1 = this.getWeekInMonth( year,month);
        let {preMonthNum ,cMonthNum} = this.getCurrentMonth(year,month);
        let preMonthDays = this.compedNextTr1(preMonthNum, cMonthWeek1);  // 获取当前页上月 arr
        return this.getAllDay(preMonthDays,cMonthNum,this.compDay)
    },
    // 获取头部以后年月
    getCurrentDate() {let currentDate = new Date();
      let year = currentDate.getFullYear();
      let month = currentDate.getMonth() + 1;
      return {year, month};
    },
    // 获取当月数据
    getCurrentMonth(year, month) {
      // 获取月有多少天
      let cMonthNum = new Date(year, month, 0).getDate();
      let preMonthNum = new Date(year, month - 1, 0).getDate();
      let nextMonthNum = new Date(year, month + 1, 0).getDate();
      return {cMonthNum, preMonthNum, nextMonthNum};
    },
    // 计算某一月 1 号是星期几
    getWeekInMonth(year, month) {return new Date(year + "/" + month + "/" + "01").getDay();},
    // 计算第一行 当月显示的日期
    compedNextTr1(preMonthNum, cMonthWeek1) {var pre = [],
        temp = cMonthWeek1;
      for (var i = 0; i < cMonthWeek1; i++) {pre.push(preMonthNum - temp + 1);
        temp--;
      }
      return pre.map(item =>{return { num:item,type:'prev'}
      })
    },
    // 组成当月日期的数组
    compDay(cMonthNum,typer) {var cDay = Array.from({ length: cMonthNum}, (v, k) =>{return k + 1;});
      return cDay.map(item =>{return { num:item,type: typer=='next'?'next':'current'}
      })
    },
    // 获取所有的
    getAllDay(preMonthDays,cMonthNum,compDay) {var preAndCenter = preMonthDays.concat(compDay(cMonthNum));
      var lastDayNum = 7 - (preAndCenter.length % 7);
      var allDays = preAndCenter.concat(compDay(lastDayNum,'next'));
      return allDays
    },
    monthSwitch(type){let { year,month} = this.headerData
        if(type == 'prev'){if(month == 1){
                this.headerData.month =12
                this.headerData.year = year - 1
                this.allDays = this.computer(this.headerData.year,this.headerData.month)
            }else{
                this.headerData.month = this.headerData.month -1
                this.allDays = this.computer(year,month-1)
            }
        }
        if(type == 'next'){if(month == 12){
                this.headerData.month =1
                this.headerData.year = year + 1
                this.allDays = this.computer(this.headerData.year,this.headerData.month)
            }else{
                this.headerData.month = this.headerData.month +1
                this.allDays = this.computer(year,month+1)
            }
        }
    },
    // 依据传入的日期标记
    getMark(marks,currentYear,currentMonth){
        const dayMarks = marks.filter(item=>{let zday = (new Date(item))
            if(zday.getMonth()+1 == currentMonth && zday.getFullYear() == currentYear){return zday.getDate()
            }   
        })
        const matchDays = dayMarks.map(item => (new Date(item)).getDate())
        this.allDays.forEach(item =>{ delete item.mark})
        this.allDays.forEach(item=>{
          matchDays.forEach(item2=>{if(item.num == item2){item.mark = true}
          })
        })
        this.$forceUpdate()},


  },
};
</script>

<style scoped>
.calendar_mod {
  border: 1px solid #333;
  user-select: none;
}

.header_warp,
.week_warp,
.cell_warp {display: flex;}
.header_warp {
  height: 50px;
  border: 1px solid rgb(143, 53, 53);
  justify-content: space-between;
}
.header_btn{
    width: 100px;
    text-align: center;
    background-color: #999;
    cursor: pointer;

}
.week_item {
  flex: 1;
  text-align: center;
  border: 1px solid rgb(94, 179, 119);
}
.cell_warp {flex-wrap: wrap;}
.cell_box {
  height: 70px;
  flex: 0 0 14.285%;
  margin: 5px 0;
}
.cell_box div{
    width: 50px;
    height: 100%;
    margin: 0 auto;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;

}
.cell_box .prev{background-color: #f1b9b9;}
.cell_box .next{background-color: #b9f1c1;}
.marking{color:red;}
</style>

正文完
 0