原理
现在的日历分为两种开头: 1. '日', '一', '二', '三', '四', '五', '六'
2. '一', '二', '三', '四', '五', '六', '日'
一行7个日期,一共6行
其实不管哪种都一样,首先要确定第一行1号
在哪个位置。 如果说是 '日', '一', '二', '三', '四', '五', '六'
,那么getDay()
是几,它前面就该补几位。当前是2023-7-1
,这天是星期六,getDay() === 6
前面补六天
,如果是星期天getDay()===0
前面不用补。这里就要去取上个月多少天了,减去这六天,就可以把前面的空补上。例如:上个月是6月,有30天,30-6+1=25
,从25补到30就可以了。这里是需要判断闰年这些的,防止在2月取的不对。 第一行
补多少天算完,直接循环当月的天数。7月是31天,直接循环渲染31天
。现在算最后面
还需要补多少天,6行一共42天,现在渲染了6+31=37
天,还需要补42-37=5
天。
其实不管哪种都一样,首先要确定第一行1号
在哪个位置。 如果说是 '一', '二', '三', '四', '五', '六','日'
,这里就有点小区别了。假设n=getDay()
,应该补n-1
天, 但是星期日例外,星期日的n=0
但是它要补6天
。当前是2023-7-1
,这天是星期六,getDay() === 6
前面补五天
,如果是星期天getDay()===0
前面补六天。 第一行
补多少天算完,直接循环当月的天数。7月是31天,直接循环渲染31天
。现在算最后面
还需要补多少天,6行一共42天,现在渲染了5+31=36
天,还需要补42-36=6
天。
源码
< template>
< div>
< div class = " toolbar" >
< div class = " btn" @click = " preMonth" > 上一月</ div>
< div class = " date" > {{ currentYear }}年{{ currentMonth }}月</ div>
< div class = " btn" @click = " nextMonth" > 下一月</ div>
</ div>
< div class = " container" >
< div v-for = " (item, index) in header" :key = " index" class = " grid-item" > {{ item }}</ div>
< div v-for = " (item, index) in lastMonthSurplusDayArray" :key = " index" class = " grid-item" >
{{ item }}
</ div>
< div
v-for = " (item, index) in currentMonthDayCount"
:key = " index"
:class = " [
'grid-item',
Math.random() * 30 < 10
? 'very-hot'
: Math.random() * 30 < 20
? 'middle-hot'
: 'normal-hot'
]"
>
{{ item }}
</ div>
< div v-for = " (item, index) in nextMonthSurplusDayArray" :key = " index" class = " grid-item" >
{{ item }}
</ div>
</ div>
</ div>
</ template>
< script setup lang = " ts" >
import { reactive, ref, onMounted } from 'vue'
const header = reactive< string[ ] > ( [ '一' , '二' , '三' , '四' , '五' , '六' , '日' ] )
const lastMonthSurplusDay = ref< number> ( 0 )
const lastMonthSurplusDayArray = ref< number[ ] > ( [ ] )
const nextMonthSurplusDay = ref< number> ( 0 )
const nextMonthSurplusDayArray = ref< number[ ] > ( [ ] )
const currentMonthDayCount = ref< number> ( 0 )
const currentYear = ref< number> ( 0 )
const currentMonth = ref< number> ( 0 )
const currentDate = ref< number> ( 0 )
const leapMonthDay = reactive< number[ ] > ( [ 31 , 29 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ] )
const normalMonthDay = reactive< number[ ] > ( [ 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ] )
function isLeapYear ( year : number) {
return ( year % 4 === 0 && year % 100 !== 0 ) || year % 400 === 0
}
function getMonthFirstDay ( year : number, month : number) {
return new Date ( year, month - 1 , 1 ) . getDay ( )
}
function calculateDays ( ) {
lastMonthSurplusDay. value =
getMonthFirstDay ( currentYear. value, currentMonth. value) === 0
? 6
: getMonthFirstDay ( currentYear. value, currentMonth. value) - 1
currentMonthDayCount. value = isLeapYear ( currentYear. value)
? leapMonthDay[ currentMonth. value - 1 ]
: normalMonthDay[ currentMonth. value - 1 ]
let prevMonthLastDate = 0
if ( currentMonth. value === 1 ) {
prevMonthLastDate = isLeapYear ( currentYear. value - 1 )
? leapMonthDay[ leapMonthDay. length - 1 ]
: normalMonthDay[ normalMonthDay. length - 1 ]
} else {
prevMonthLastDate = isLeapYear ( currentYear. value)
? leapMonthDay[ currentMonth. value - 2 ]
: normalMonthDay[ currentMonth. value - 2 ]
}
nextMonthSurplusDay. value = 42 - ( lastMonthSurplusDay. value + currentMonthDayCount. value)
const prevtemp = [ ]
const nexttemp = [ ]
for ( let i = prevMonthLastDate - lastMonthSurplusDay. value + 1 ; i <= prevMonthLastDate; i++ ) {
prevtemp. push ( i)
}
for ( let i = 1 ; i <= nextMonthSurplusDay. value; i++ ) {
nexttemp. push ( i)
}
lastMonthSurplusDayArray. value = prevtemp
nextMonthSurplusDayArray. value = nexttemp
}
function preMonth ( ) {
if ( currentMonth. value === 1 ) {
currentMonth. value = 12
-- currentYear. value
} else {
-- currentMonth. value
}
calculateDays ( )
}
function nextMonth ( ) {
if ( currentMonth. value === 12 ) {
currentMonth. value = 1
++ currentYear. value
} else {
++ currentMonth. value
}
calculateDays ( )
}
function getCurrentDate ( ) {
const d = new Date ( )
const year = d. getFullYear ( )
const month = d. getMonth ( ) + 1
const date = d. getDate ( )
return {
year,
month,
date
}
}
function initCalendar ( ) {
const { year, month, date } = getCurrentDate ( )
currentYear. value = year
currentMonth. value = month
currentDate. value = date
calculateDays ( )
}
onMounted ( ( ) => {
initCalendar ( )
} )
</ script>
< style scoped >
.toolbar {
display : flex;
width : 100%;
height : 50px;
}
.toolbar .date {
flex : 1;
color : #333;
font-size : 14px;
font-weight : bold;
text-align : center;
line-height : 30px;
border-top : 1px solid #eee;
padding : 10px;
box-sizing : border-box;
}
.toolbar .btn {
flex : 1;
color : #1d84f6;
text-align : center;
line-height : 30px;
border-top : 1px solid #eee;
border-left : 1px solid #eee;
border-right : 1px solid #eee;
padding : 10px;
box-sizing : border-box;
}
.container {
display : grid;
box-sizing : border-box;
grid-template-columns : auto auto auto auto auto auto auto;
border-top : 1px solid #eee;
border-left : 1px solid #eee;
border-right : 1px solid #eee;
}
.grid-item {
width : 50px;
height : 50px;
line-height : 50px;
border-bottom : 1px solid #eee;
border-right : 1px solid #eee;
font-size : 14px;
text-align : center;
}
.grid-item:nth-child(7n) {
border-right : none;
}
.very-hot {
background-color : #e10231;
}
.middle-hot {
background-color : #fe4806;
}
.normal-hot {
background-color : #ffb508;
}
</ style>