React获取最近三个月的日期组件

2020-10-31  本文已影响0人  Lia代码猪崽
image.png

需求分析

  1. 根据当前日期,获取到这个月、下个月、下下个月的时间日期。
  2. 可以拆分成三个组件:月、周、日。
  3. 每月的首周和最后一周不一定都填满,需要根据第一天和最后一天是周几来决定要补充多少个空的日期,不然周组件渲染会有错误。
  4. 如果是当天,要特殊样式处理。
  5. 如果是周六/周日,要特殊样式处理。

完整代码

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>
  )
}, [])
上一篇下一篇

猜你喜欢

热点阅读