自定义具有简单日志功能的日历组件

该组件除了日志的功能外,还可以展示博客等数据的更新日期。
在这里插入图片描述

主要难点在于如何确定每一个月的每一天在表格中的具体位置。建立一个7*7的二维数组,每一行代表每一周,其中第一行是“星期日”直“星期六”;根据JSnew Date()方法获取,每一年每一个月的第一天(1日)是星期几,接下来从第二行起按照日期顺序将日期填入二维数组。需要注意的是,每一个月的有多少天要根据实际情况来进行分别判断;另外,1日以前的上月月尾和本月月尾后的下月月初的日期填入二维数组时,注意要根据一定规律来进行填写。

当代表一个月的二维数组建立之后,还需要为当月的每一天增加一些数据。例如从后台请求回来的更新数据,在数组中的日期并不是都是当月的日期,所以需要加是否为当月日期的标志等,最后就可以按照该数组建立表格,根据数据内容增加相应的样式。

Calendar.js代码如下:

import React, { Component } from 'react'
import './Calendar.scss'

class Calendar extends Component {
    constructor(props) {
        super(props);

        this.state = {
            today: {
                year: new Date().getFullYear(),
                month: new Date().getMonth() + 1,
                day: new Date().getDate(),
                week: new Date().getDay(), // 0-6, 0代表星期天
            },
            selectDate: {
                year: new Date().getFullYear(),
                month: new Date().getMonth() + 1
            },
            data: [
                { date: '1588464000000', content: '内容1' },
                { date: '1589904000000', content: '内容2' }
            ]
        }
    }

    fetchData = (url,params)=>{
        if(!url) return;
        if (params) {
            let paramsArray = [];
            //拼接参数
            Object.keys(params).forEach(key => paramsArray.push(key + '=' + params[key]))
            if (url.search(/\?/) === -1) {
                url += '?' + paramsArray.join('&')
            } else {
                url += '&' + paramsArray.join('&')
            }
        }
        fetch(url, {
            method: 'GET'
        }).then(res => res.json()).then(
            (data) => {
                if (data.result.length > 0) {
                    this.setState({
                        ...this.state, ...data.result
                    });
                } 
            }
        );
    }

    componentDidMount(){
        this.fetchData(this.props.url, this.state.selectDate);
    }

    isLeapYear = (year) => {
        if ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0)) {
            return true;
        }
        return false;
    }

    getMonthDayArr = (year, month) => {
        const firstDay = new Date(year + '-' + month + '-' + '01');
        const weekDay = firstDay.getDay();

        var dayObj = {
            day: 1, 
            month : 1, 
            year : 2020,
            isThisMonth: true, //是否属于当月
            isCurrentToday : false,//是否是当天
            isCurrentMonth : false,//是否是当月
            data : ''//从服务器请求回来的数据
        };

        var today = new Date().getDate();

        var monthArr = [], week = -1, flag = 1; 
        for (let index = 0; index < 49; index++) {
            const wd = index%7;
            if(wd === 0){
                week ++ ;
                monthArr[week]=[];
            }

            if(week === 0){
                monthArr[week] = [
                    { day: '日', data: '', isThisMonth: true},
                    { day: '一', data: '', isThisMonth: true},
                    { day: '二', data: '', isThisMonth: true},
                    { day: '三', data: '', isThisMonth: true},
                    { day: '四', data: '', isThisMonth: true},
                    { day: '五', data: '', isThisMonth: true},
                    { day: '六', data: '', isThisMonth: true }] 
            }else{
                monthArr[week][wd] = Object.assign({}, dayObj);
                if (week === 1) {
                    if (wd === weekDay){
                        monthArr[week][wd]['day'] = 1;
                    } else if (wd > weekDay){
                        monthArr[week][wd]['day'] = 1 + wd - weekDay;
                    }else {
                        if(month - 1 === 2 && this.isLeapYear(year)){
                            monthArr[week][wd]['day'] = 29 - (weekDay - wd) + 1;
                            monthArr[week][wd]['isThisMonth'] = false;
                        } else if(month - 1 === 2 && !this.isLeapYear(year)){
                            monthArr[week][wd]['day'] = 28 - (weekDay - wd) + 1;
                            monthArr[week][wd]['isThisMonth'] = false;
                        } else if (month - 1 === 1 || month - 1 === 3 || month - 1 === 5 || month - 1 === 7 || month - 1 === 8 || month - 1 === 10 || month - 1 === 12){
                            monthArr[week][wd]['day'] = 31 - (weekDay - wd) + 1;
                            monthArr[week][wd]['isThisMonth'] = false;
                        } else {
                            monthArr[week][wd]['day'] = 30 - (weekDay - wd) + 1;
                            monthArr[week][wd]['isThisMonth'] = false;
                        }
                        
                     }
                }else{
                    if (month === 2 && this.isLeapYear(year)) {
                        if (monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd > 29) {
                            monthArr[week][wd]['day'] = flag;
                            monthArr[week][wd]['isThisMonth'] = false;
                            flag ++ ;
                        } else {
                            monthArr[week][wd]['day'] = monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd;
                        }
                    } else if (month === 2 && !this.isLeapYear(year)) {
                        if (monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd > 28) {
                            monthArr[week][wd]['day'] = flag;
                            monthArr[week][wd]['isThisMonth'] = false;
                            flag++;
                        } else {
                            monthArr[week][wd]['day'] = monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd;
                        }
                    } else if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
                        if (monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd > 31) {
                            monthArr[week][wd]['day'] = flag;
                            monthArr[week][wd]['isThisMonth'] = false;
                            flag++;
                        } else {
                            monthArr[week][wd]['day'] = monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd;
                        }
                    } else {
                        if (monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd > 30) {
                            monthArr[week][wd]['day'] = flag;
                            monthArr[week][wd]['isThisMonth'] = false;
                            flag++;
                        } else {
                            monthArr[week][wd]['day'] = monthArr[1][6]['day'] + 7 * (week - 2) + 1 + wd;
                        }
                    }
                }
            }
            for (let j = 0; j < this.state.data.length; j++) {
                const el = this.state.data[j];
                let d = el.date;

                let dYear = new Date(parseInt(d)).getFullYear();
                let dMonth = new Date(parseInt(d)).getMonth() + 1;
                let dDate = new Date(parseInt(d)).getDate();

                if (month === dMonth && year === dYear && monthArr[week][wd]['day'] === dDate && monthArr[week][wd]['isThisMonth']) {
                    monthArr[week][wd]['data'] = el.content;
                }

            }
            if (monthArr[week][wd]['day'] === today && month === this.state.today.month){
                monthArr[week][wd]['isToday'] =  true;
            }
        }

        return monthArr;
    }

    pre=()=>{
        let month = this.state.selectDate.month;
        let year =  this.state.selectDate.year;
        let state = this.state;
        if(month === 1){
            month = 12;
            year = year - 1;
        }else{
            month = month - 1;
        }

        this.setState({
            state, ...{
                selectDate: {
                    year: year,
                    month: month
                }
        }});

        if (this.props.url) {
            this.fetchData(this.props.url, this.state.selectDate);
        }
    }

    next=()=>{
        let month = this.state.selectDate.month;
        let year = this.state.selectDate.year;
        let state = this.state;
        if (month === 12) {
            month = 1;
            year = year + 1;
        } else {
            month = month + 1;
        }
        this.setState({
            state, ...{
                selectDate: {
                    year: year,
                    month: month
                }
            }
        });

        if (this.props.url) {
            this.fetchData(this.props.url, this.state.selectDate);
        }
    }

    componentDidMount(){

    }

    getDayStyle=(dayObj)=>{
        let notThisMonthDayStyle = {};

        notThisMonthDayStyle ={
            color: dayObj['isThisMonth'] ? '' : 'grey',
            backgroundColor: dayObj['data'] ? 'rgb(157, 252, 169)' : '',
            fontWeight: dayObj['isToday'] ? 'bolder' : ''
        }

        return notThisMonthDayStyle;
    }

    render() {
        const styles = {
            width: this.props.style.width,
            height: this.props.style.height,
            margin: this.props.style.margin
        }

        let month = [], week =[];
        const monthArr = this.getMonthDayArr(this.state.selectDate.year, this.state.selectDate.month);
    
        for (let index = 0; index < monthArr.length; index++) {
            const element = monthArr[index];
            week = [];
            if (!element[element.length - 1]['isThisMonth'] && index === 1){

            } else if (!element[0]['isThisMonth'] && index === 6){

            }else{
                for (let i = 0; i < element.length; i++) {
                    const e = element[i];
                    if (e.data){
                        week.push(<td key={'calendar-td' + index + i} style={this.getDayStyle(e)}>{e['day']}<span>{e.data}</span></td>);
                    }else{
                        week.push(<td key={'calendar-td' + index + i} style={this.getDayStyle(e)}>{e['day']}</td>);
                    }
                   
                }
            }
            
            month.push(<tr key={'calendar-tr'+index}>{week}</tr>);
        }
        
        return (
            <div className='calender-div' style={styles}>
                <div className='calender-select-date-div'>
                    <div className='calender-preMonth'><button onClick={this.pre}>上一月</button></div>
                    <div className='calendar-select-date-div-date-div'>{this.state.selectDate.year + '年' + this.state.selectDate.month + '月'}</div>
                    <div className='calender-nextMonth'><button onClick={this.next}>下一月</button></div>
                </div>
                <div className='calender-month-div'>
                    <table className='calender-month-table'><tbody>{month}</tbody></table>
                </div>
            </div>)
    }

}

Calendar.defaultProps = {
    style: {
        width: '220px',
        height: '200px',
    },
    data : [
        { date: '1588464000000', content:'举例:更新内容1'},
        { date: '1589904000000', content: '举例:更新内容2' }
    ],
    url:''
};

export default Calendar;


Calendar.scss样式文件

$textSize: 10px;
$border: 1px solid grey;
.calender-select-date-div {
  height: 12%;
  width: 100%;
  display: table;
  font-size: $textSize;
  button {
    background-color: white;
    font-size: $textSize;
    border: 1px;
    &:hover {
      cursor: pointer;
    }
  }

  .calendar-select-date-div-date-div {
    height: 100%;
    display: table-cell;
    width: 50%;
    text-align: center;
    vertical-align: middle;
  }

  .calender-preMonth {
    display: table-cell;
    vertical-align: middle;
    text-align: right;
  }

  .calender-nextMonth {
    display: table-cell;
    vertical-align: middle;
    text-align: left;
  }
}

.calender-month-div {
  height: 88%;
  width: 100%;
  border-top: $border;
}

.calender-div {
  border: $border;
  margin: 10px 10px 10px 10px;
}

$tdWidth: 100%;

.calender-month-table {
  table-layout: fixed;
  word-break: break-all;
  height: 100%;
  width: 100%;
  font-size: $textSize;
  td {
    width: $tdWidth/7;
    vertical-align: middle;
    text-align: center;
    position: relative;
    cursor:default;
    span {
      visibility: hidden;
      background-color: rgb(157, 252, 169);
      color: black;
      text-align: center;
      padding: 5px 0;
      border-radius: 2px;
      /*定位*/
      position: absolute;
      z-index: 1;
      -webkit-border-radius: 2px;
      -moz-border-radius: 2px;
      -ms-border-radius: 2px;
      -o-border-radius: 2px;
    }
    &:hover span {
      visibility: visible;
      width: 120px;
      left: 25px;
      top: -30px;
    }
  }
}


从服务器请求回来的数据格式为:

{
    .
    .
    result : [{ date: '1588464000000', content: '内容1' },
                { date: '1589904000000', content: '内容2' }],
    .
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值