image.png
需求分析
- 根据当前日期,获取到这个月、下个月、下下个月的时间日期。
- 可以拆分成三个组件:月、周、日。
- 每月的首周和最后一周不一定都填满,需要根据第一天和最后一天是周几来决定要补充多少个空的日期,不然周组件渲染会有错误。
- 如果是当天,要特殊样式处理。
- 如果是周六/周日,要特殊样式处理。
完整代码
import React, { memo } from 'react'
import dayjs from 'dayjs'
import { classnames } from 'classnames '
import './style.module.scss'
// 找到这个日期的月份的第一天的零时零分零秒
const firstDayTimeInMonth = (timestamp = new Date().getTime()) => {
const date = new Date(timestamp)
date.setDate(1)
date.setHours(0)
date.setMinutes(0)
date.setSeconds(0)
date.setMilliseconds(0)
return date.getTime()
}
export default function Calendar() {
const now = new Date()
const months = []
months.push(firstDayTimeInMonth(now))
now.setMonth(now.getMonth() + 1)
months.push(firstDayTimeInMonth(now))
now.setMonth(now.getMonth() + 1)
months.push(firstDayTimeInMonth(now))
return (
<div className="calendar">
{months.map((month) => (
<Month key={month} startTimeInMonth={month}></Month>
))}
</div>
)
}
function Month(props) {
const { startTimeInMonth } = props
const startDate = new Date(startTimeInMonth)
const currentDay = new Date(startTimeInMonth)
let days = []
while (startDate.getMonth() === currentDay.getMonth()) {
days.push(currentDay.getTime())
currentDay.setDate(currentDay.getDate() + 1)
}
days = new Array(startDate.getDay() ? startDate.getDay() - 1 : 6)
.fill(null)
.concat(days)
const lastDate = new Date(days[days.length - 1])
days = days.concat(
new Array(lastDate.getDay() ? 7 - lastDate.getDay() : 0).fill(null)
)
const weeks = []
for (let row = 0; row < days.length / 7; row++) {
const week = days.slice(row * 7, (row + 1) * 7)
weeks.push(week)
}
return (
<div className="calendar-month">
<table className="calendar-month-content">
<thead className="calendar-month-content-title">
<tr>
<td colSpan="7">
<h5>{dayjs(startDate).format('YYYY年MM月')}</h5>
</td>
</tr>
</thead>
<tbody>
<tr>
<th>周一</th>
<th>周二</th>
<th>周三</th>
<th>周四</th>
<th>周五</th>
<th>周六</th>
<th>周日</th>
</tr>
{weeks.map((week) => (
<Week key={week} week={week}></Week>
))}
</tbody>
</table>
</div>
)
}
const Week = memo(function Week({ week }) {
return (
<tr>
{week.map((day, index) => (
<Day key={index} day={day}></Day>
))}
</tr>
)
}, [])
const Day = memo(function Day({ day }) {
const today = new Date()
today.setHours(0)
today.setMinutes(0)
today.setSeconds(0)
today.setMilliseconds(0)
const stringDay = day ? new Date(day).getDate() : ''
return (
<td
className={classnames('calendar-day', {
day === today.getTime() : 'calendar-day--today',
day < today.getTime() : 'calendar-day--pass',
})}
>
{stringDay}
</td>
)
}, [])
网友评论