我的项目要用到一个日历,然而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>