IT干货网

手写一个react日历超级简单

shasha 2022年03月15日 编程设计 176 0

概述

一个超级简单的日历,日历核心代码只有十几行,方便以后扩展成日程管理。源码点击这里

前言

日历或者日程管理,在项目中是个高频使用的组件,经常会碰到日程管理这种需求,网上已经有很多成熟的库,但是产品经理的思维是你我无法揣测的,所以先储备一下,做个简单的日历,方便以后用的的时候直接用,代码使用react写的,但是核心的日历计算思想可以用到各种框架中。

实现

首先看看最终实现的效果

可以看到一个能查看上一个月或者下一个月的简单日历。

日历的计算的核心就是通过date.setdate()方法,可以获取到相对于当前日期的某天,比如new Date().setdate(1)就是当前日期的下一天

代码很简单也有注释,就不多赘述,有不懂的地方留言,秒回

import React, {Component} from 'react'; 
import style from './style.use.less' 
 
export default class Test extends Component { 
    constructor(props) { 
        super(props); 
        this.state = { 
            currentDay: '', 
            currentMonth: '',  
            currentYear: '',  
            weekList: [ 
                {name: '一', className: ''}, 
                {name: '二', className: ''}, 
                {name: '三', className: ''}, 
                {name: '四', className: ''}, 
                {name: '五', className: ''}, 
                {name: '六', className: ''}, 
                {name: '日', className: ''} 
            ], 
            dayList: [] 
        } 
 
        this.initCalendar = this.initCalendar.bind(this); 
        this.renderHeader = this.renderHeader.bind(this); 
        this.renderBody = this.renderBody.bind(this); 
        this.preMonth = this.preMonth.bind(this); 
        this.nextMonth = this.nextMonth.bind(this); 
    } 
 
    componentWillMount() { 
      // style.use() // 需要配置loader 可以直接注释 忽略掉  实现每个模块卸载之后 css也会销毁 可以看之前写的一篇react css局部作用域的文章 
    } 
 
    componentWillUnmount() { 
       // style.unuse() // 需要配置loader 可以直接注释 忽略掉 实现每个模块卸载之后 css也会销毁 可以看之前写的一篇react css局部作用域的文章 
    } 
 
    componentDidMount() { 
        this.initCalendar() 
    } 
 
    // 获取当前date的当月第一天的字符串形式 
    getMonthFirstDate(date) { 
        let nowYear = date.getFullYear(); // 获取年份 
        let nowMonth = date.getMonth()+1; // 获取月份 
        return  `${nowYear}-${nowMonth}-01` 
    } 
 
    // 获取当前date的字符串形式 
    getDateString(date) { 
        let nowYear = date.getFullYear(); // 获取年份 
        let nowMonth = date.getMonth()+1; // 获取月份 
        let day = date.getDate(); 
        day = day < 10 ? '0' + day : day; 
        return  `${nowYear}-${nowMonth}-${day}` 
    } 
 
    // 上个月 
    preMonth() { 
        let date = new Date(`${this.state.currentYear}-${this.state.currentMonth}-${this.state.currentDay}`) 
        let preMonthFirstDate = new Date(this.getMonthFirstDate(new Date(date.setDate(0)))); // 0 是上个月最后一天 
        this.initCalendar(preMonthFirstDate) 
    } 
 
    // 下个月 
    nextMonth() { 
        let date = new Date(`${this.state.currentYear}-${this.state.currentMonth}-${this.state.currentDay}`) 
        let nextMonthFirstDate = new Date(this.getMonthFirstDate(new Date(date.setDate(33)))); 
        this.initCalendar(nextMonthFirstDate) 
    } 
 
 
    // 初始化日历 
    initCalendar(currentDate) { 
         
        let nowDate = currentDate ? currentDate : new Date(); 
        let nowMonthFirstDate = this.getMonthFirstDate(nowDate) // 获取当月1号日期 
        let nowWeek = new Date(nowMonthFirstDate).getDay() ? new Date(nowMonthFirstDate).getDay() : 7; // 获取星期 
        let newDateList = []; // 创建日期数组 
        let startDay =  2 - nowWeek; // 开始日期的下标  以为 setDate(0)是上个月最后一天  所以是2-nowWeek 
         
        let showDayLength = nowWeek < 6 ? 35 : 42;  // 如果5行能显示下一个月 就只显示5行 
        // 循环处理 获取日历上应该显示的日期 
        for (let i = startDay; i < startDay + showDayLength; i++) { 
            let date = new Date(new Date(nowMonthFirstDate).setDate(i)); // 获取时间对象 
            let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() // 小于9的数字前面加0 
            let dayObject = { 
                date: this.getDateString(date), 
                day, 
                className: '', 
            } 
            // new Date(str).toDateString() === new Date().toDateString() 
            if (date.toDateString() === new Date().toDateString()) { 
                dayObject.className = 'today' 
            } 
            newDateList.push(dayObject) 
        } 
 
        this.setState((pre) => { 
            return { 
                dayList: newDateList, 
                currentDay: nowDate.getDate(), 
                currentMonth: nowDate.getMonth() + 1 >= 10 ? nowDate.getMonth() + 1 : '0' + (nowDate.getMonth() + 1), 
                currentYear: nowDate.getFullYear(), 
            } 
        }) 
 
    } 
 
    renderHeader() { 
        return( 
            <div className = 'calendar-header'> 
                <div className = 'calendar-header-left'> 
                    <button onClick = {this.preMonth}>上个月</button> 
                </div> 
                <div className = ''> 
                    {this.state.currentYear}年{this.state.currentMonth}月 
                </div> 
                <div className = 'calendar-header-right'> 
                    <button onClick = {this.nextMonth}>下个月</button> 
                </div> 
            </div> 
        ) 
    } 
 
    renderBody() { 
        return( 
            <div className = 'calendar-body'> 
                <div className = 'week-container'> 
                    {this.state.weekList.map(week => { 
                        return <div key = {week.name} className = {`week ${week.className}`}>{week.name}</div> 
                    })} 
                </div> 
                <div className = 'day-container'> 
                    {this.state.dayList.map( (dayObject, index) => { 
                        return <div key = {index} className = {`day ${dayObject.className}`}>{dayObject.day}</div> 
                    })} 
                </div> 
            </div> 
        ) 
    } 
 
    render() { 
        return( 
            <div className = 'calendar'> 
                {this.renderHeader()} 
                {this.renderBody()} 
            </div> 
        ) 
    } 
} 

css文件

.calendar { 
    width: 320px; 
    margin-top: 40px; 
    .calendar-header { 
        display: flex; 
        justify-content: space-between; 
        padding: 14px 12px;  
    } 
    .calendar-body { 
        .week-container { 
            display: flex; 
            flex-wrap: wrap; 
            justify-content: space-around; 
            margin-bottom: 10px; 
            .week { 
                &:nth-child(6), &:nth-child(7){ 
                    color: #e02d2d; 
                } 
                width: 14.2%; 
                display: inline-block; 
                text-align: center; 
            } 
        } 
 
        .day-container { 
            height: 140px; 
            display: flex; 
            flex-wrap: wrap; 
            justify-content: space-around; 
            .day { 
                width: 14.2%; 
                display: inline-block; 
                text-align: center; 
                &:nth-child(7n-1){ 
                    color: #e02d2d; 
                } 
                &:nth-child(7n){ 
                    color: #e02d2d; 
                } 
                &.today { 
                    color: green; 
                } 
            } 
  
        } 
    } 
} 

评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

react 拖拽上传