一个简单日历的实现

前言

哪怕再简单的组件, 自己实现之后, 都会有收获.

日历主要逻辑

  1. 日历主要展示了每个月有多少天, 以及对应是星期几, 因此需要一个时间函数, 通过这个函数, 我可以输入年和月, 返回本月有多少天.
  2. 日历需要循环展示日期, 因此我需要一个数组. 为了日后的扩展需要, 数组之中应该是一个对象.
  3. 本次日历还需要展示上月和下月的几天, 我又需要知道本月的1号和最后一号是周几, 上月需要显示几天, 下月需要显示几天.
  4. 整百年与非整百年的润年判定.
  5. 点击事件与UI的整体展示

代码实现

本文所使用的select组件在我的如何定制一个下拉框一文中有




import React, { Component } from 'react'
import Select from '../components/Select'


export default class extends Component {
	constructor(props){
		super(props)
		this.state={
			calendar: '日历', 
			monthArr: [],
			yearArr: [],
			dayArr: [],
			calendarHead: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', ],
			selectTime: '0',
			selectYear: '',
			selectMonth: ''
		}
		this.getTime = this.getTime.bind(this);
		this.getPreArr = this.getPreArr.bind(this);
		this.getNextArr = this.getNextArr.bind(this)
		this.getDayArr = this.getDayArr.bind(this)
		this.getDayNum = this.getDayNum.bind(this)
		this.initState = this.initState.bind(this)
		this.getNumArr = this.getNumArr.bind(this)
		this.selectDay = this.selectDay.bind(this)
		this.pickYear = this.pickYear.bind(this)
		this.pickMonth = this.pickMonth.bind(this)
	}

	componentDidMount(){
		this.initState()
	}
	initState(){
		let { year, month, timeStr } = this.getTime()
		let dayArr = this.getDayArr()  
		let yearArr = this.getNumArr(2012, 15)
		let monthArr = this.getNumArr(1,12)
		let selectYear = year 
		let selectMonth = month
		this.setState({dayArr, yearArr, monthArr, year, month, timeStr, selectYear, selectMonth})
	}

	getNumArr(init, length){
		let arr = []
		for(let i=0;i<length; i++){
			arr.push(init+i)
		} 
		
		return arr
	}
	getTime(time){
		let date =time? new Date(time): new Date();
		let year = date.getFullYear();
		let month = date.getMonth() + 1;
		let day = date.getDate();
		let week = date.getDay();
		let timeStr = `${year}-${month}-${day}`
			return { year, month, day, week, timeStr }
	}

	getDayNum(year,month){
		let arr= [1,3,5,7,8,10,12]
		let num = year%100===0 ? 400 : 4
		let isLeap =  year%num===0       //计算闰年
		if(arr.indexOf(month)!==-1){
			return 31
		}
		else if(month===2&isLeap){
			return 29
		}
		else if(month===2){
			return 28
		}
		else return 30
	}
	getDayArr(str){
		let { year, month} = this.getTime(str)
		let monthNum = this.getDayNum(year, month)  //本月有天数
		let preMonth = month-1===0 ? 12 :month-1
		let preYear =  preMonth===12 ?   year-1 : year
		let nextMonth = month+1===13 ? 1 : month+1
		let nextYear = nextMonth===1 ? year+1 :year
		let preMonthNum = this.getDayNum(preYear, preMonth)  //前月天数
		let firWeek = this.getTime(`${year}-${month}-1`).week  //本月初是周几
		let lastWeek = this.getTime(`${year}-${month}-${monthNum}`).week
		let length = 6-lastWeek
		let preArr = this.getPreArr(preYear, preMonth,preMonthNum, firWeek )
		let nextArr = this.getNextArr(nextYear, nextMonth,length )
		let arrs = []
		// let arr=[]
			for(let i=0; i<monthNum; i++){
				let week = i%7
				let days = i+1
				let time =`${year}-${month}-${days}`
				let isMain = true
				arrs.push({week, days, time, isMain})
			}
		let array = [...preArr, ...arrs, ...nextArr]
		return array
		// let arr = []
		// function getObj()
	}



	getPreArr(year, month, monthNum, length){
		let arr = []
		for(let i=0; i<length; i++){
			let week = i
			let days = monthNum - length+i+1
			let time = `${year}-${month}-${days}`
			let isMain =false 
			arr.push({week, days, time, isMain})
		}
		return arr
	}

	getNextArr(nextYear, nextMonth, length){
		let arr = []
		for(let i=0;i<length;i++){
			let week = 6-length+i+1
			let days = i+1
			let time = `${nextYear}-${nextMonth}-${days}`
			let isMain = false
			arr.push({week, days, time, isMain})
		}
		return arr
	}
	selectDay(e){
		let { time } = e.currentTarget.dataset 
		this.setState({ selectTime: time })
	}

	pickYear(year){
		let { selectMonth } = this.state
		this.setState({ selectYear: year })
		let str = `${year}-${selectMonth}-1`
		let dayArr = this.getDayArr(str)
		this.setState({ dayArr })
		console.log('pickYear',this.getDayArr(str))
	}

	pickMonth(month){
		let { selectYear } = this.state
		this.setState({ selectMonth: month })
		let str = `${selectYear}-${month}-1`
		let dayArr = this.getDayArr(str)
		this.setState({ dayArr })
	}
	render(){
		let { yearArr, monthArr, year, month, dayArr, calendarHead, timeStr, selectTime } = this.state
		// console.log(this.state)
		return (
			<div>
				<div className='calendar-title' >简单日历</div>
				<div className='calendar-select-header' >
					<Select valueArr={ yearArr } 
									cb={ this.pickYear } 
									width={ 150 }  
									initSelect={ year }/>
					<Select valueArr={ monthArr } width={ 150 }
									cb={ this.pickMonth }
									initSelect={ month } />
				</div>
				<div className='calendar-day-container' >
					{
						calendarHead.map((item, index) =>
							<div className='calendar-day' key={ index } >{item}</div>)
					}
					{
						dayArr.map((item, index) => 
							<div className={`calendar-day ${item.isMain?'calendar-day-select': 'not-main'} ${timeStr===item.time? 'calendar-day-now': ''}  ${selectTime===item.time? 'calendar-days-pick' : '' }`} 
									 key={ index } 
									 title={ item.time }
									 data-time={ item.time }
									 onClick={ this.selectDay }>{item.days}</div>)
					}
				</div>
			</div>
			)
	}
}
复制代码

效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值