ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

React 实现自定义日历

2022-01-14 10:34:17  阅读:314  来源: 互联网

标签:index 215 const 自定义 日历 React moment export import


项目中又遇到了自定义日历,记录下来,方便以后抄代码~~0_0~

自定义日历最重要的三步:

  1. 找到当前月有多少天,以及第一天是星期几--灰常重要!
  2. 根据第一步找到需要填充的上月的日期,因为第一步中获取的到下标刚好是需要显示的上个月的天数
  3. 根据第一步,第二步获取需要填充的下个月的日期

这里是基于moment实现的~

先介绍几个moment方法:

一 :moment.weekdaysMin()

获取缩写的星期

二: moment().daysInMonth()

获取当前月的天数

三: moment().startOf('month').weekday()

获取当前月第一天是星期几

 四: moment().subtract(1, 'month')

获取上个月月份

 

 四: moment().add(1, 'month')

获取下个月月份

 上代码:

index.jsx

import React, { useState } from 'react';
import classnames from 'classnames';
import { initCalendar } from '../utils';
import { Typography } from 'antd';
import Header from '../header';

import './index.less';

export default function Content({ className }) {
  const [days, setDays] = useState(initCalendar());
  const [active, setActive] = useState(0);

  return (
    <div className={classnames('content_container', className)}>
      <div className={classnames('toolbar_container', className)}>
        <Space>
          <Button icon={<LeftOutlined />} type="text" onClick={handleUp} />
          {currentMonth.format(YEAER_MONTH_FORMAT_ZH)}
          <Button icon={<RightOutlined />} type="text" onClick={handleDown} />
        </Space>
      </div>
      <div className="content_wrapper">
        {days?.map((day, index) => (
          <div
            onClick={() => setActive(index)}
            className={classnames('day_container', {
              active: index === active,
            })}
            key={index}
          >
            <Typography.Text>{day}</Typography.Text>
          </div>
        ))}
      </div>
    </div>
  );
}

index.less

.content_container {
  width: 100%;
  height: 100%;
  .toolbar_container {
    display: flex;
    justify-content: center;
    border: 1px solid rgb(215 215 215);
    background: white;
  }
  .calendar_content_wrapper {
    width: 100%;
    height: 100%;
    display: grid;
    border: 1px solid rgb(215 215 215);
    grid-template-columns: repeat(7, 1fr);
    background: white;
    .day_container {
      display: flex;
      justify-content: center;
      height: 100px;
      box-sizing: content-box;
      border-right: 1px solid rgb(215 215 215);
      border-bottom: 1px solid rgb(215 215 215);
      cursor: pointer;
      position: relative;
      .more {
        position: relative;
        width: 23px;
        height: 23px;
        border: 1px solid #000;
        left: 0;
        bottom: 0;
      }
    }

    .date_title {
      display: inline-block;
      width: 24px;
      height: 20px;
      line-height: 20px;
      margin-left: 4px;
      text-align: center;
      font-size: 16px;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: rgb(103 113 122);
    }
    .active {
      box-shadow: inset 0px 0px 5px 1px lightgreen;
    }
    .isToday {
      background: lightgreen;
    }
  }
}

utils.js

import moment from 'moment';
import { YEAER_MONTH_FORMAT, INIT_DAYS } from './const';
/**
 * 获取当前月的天数
 */
console.log(moment().format('YYYY-MM-DD'), 'moment()');
export function getMonthDays() {
  return moment().daysInMonth();
}

/**
 * 获取当前月第一天是星期几
 */
export function getWeekDays() {
  return moment().startOf('month').weekday();
}

/**
 * 获取上个月份
 */
export function getLastMonth() {
  return moment().subtract(1, 'month').format(YEAER_MONTH_FORMAT);
}

/**
 * 获取下个月份
 */
export function getNextMonth() {
  return moment().add(1, 'month').format(YEAER_MONTH_FORMAT);
}

/**
 * 初始化日历
 */
export function initCalendar() {
  // 当前月天数
  const totalDaysInMonth = getMonthDays();
  // 上个月天数
  let totalDaysInLastMonth = getMonthDays(getLastMonth());
  // 下个月开始日期
  let nextFirstDate = 1;

  const lastDays = [],
    currentDays = [],
    nextDays = [];

  // 当前月第一天是星期几(索引值)
  /**
   * 这里的索引值刚刚好是需要填充的上月的天数
   */
  const currentWeekDay = getWeekDays();

  for (let i = 0, len = 42; i < len; i++) {
    // 填充上个月的天数
    if (i < currentWeekDay) {
      lastDays.push(totalDaysInLastMonth);
      totalDaysInLastMonth--;
    }
    // 填充下个月的天数
    else if (i >= totalDaysInMonth + currentWeekDay) {
      nextDays.push(nextFirstDate);
      nextFirstDate++;
    }
    // 填充当前月天数
    else {
      currentDays.push(i - currentWeekDay + 1);
    }
  }
  // 上个月需要倒序显示
  return [...lastDays.reverse(), ...currentDays, ...nextDays];
}

const.js

import moment from 'moment';

export const YEAER_MONTH_FORMAT_ZH = 'YYYY年MM月';
export const YEAER_MONTH_FORMAT_EN = 'YYYY-MM';
export const YEAER_MONTH_FORMAT_FULL = 'YYYY-MM-DD';
// 获取星期
const [_, ...rest] = moment.weekdaysMin();

// 将星期天放置数组最后
export const WEEk_HEADER = [...rest, _];

// 日历布局为6 * 7单元格
export const TOTAL_LENGTH = 6 * 7;

// 初始化一下下
export const INIT_DAYS = Array(TOTAL_LENGTH)
  .fill(0)
  .map((_, index) => +index + 1);

标签:index,215,const,自定义,日历,React,moment,export,import
来源: https://blog.csdn.net/weixin_41718879/article/details/122487800

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有