前言
哪怕再简单的组件, 自己实现之后, 都会有收获.
日历主要逻辑
- 日历主要展示了每个月有多少天, 以及对应是星期几, 因此需要一个时间函数, 通过这个函数, 我可以输入年和月, 返回本月有多少天.
- 日历需要循环展示日期, 因此我需要一个数组. 为了日后的扩展需要, 数组之中应该是一个对象.
- 本次日历还需要展示上月和下月的几天, 我又需要知道本月的1号和最后一号是周几, 上月需要显示几天, 下月需要显示几天.
- 整百年与非整百年的润年判定.
- 点击事件与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>
)
}
}
复制代码