一個超級簡單的日曆,日曆核心代碼只有十幾行,方便之後擴展成日程管理。源碼點擊這裏css
日曆或者日程管理,在項目中是個高頻使用的組件,常常會碰到日程管理這種需求,網上已經有不少成熟的庫,可是產品經理的思惟是你我沒法揣測的,因此先儲備一下,作個簡單的日曆,方便之後用的的時候直接用,代碼使用react寫的,可是核心的日曆計算思想能夠用到各類框架中。react
首先看看最終實現的效果
能夠看到一個能查看上一個月或者下一個月的簡單日曆。git
日曆的計算的核心就是經過date.setdate()方法,能夠獲取到相對於當前日期的某天,好比new Date().setdate(1)就是當前日期的下一天github
代碼很簡單也有註釋,就很少贅述,有不懂的地方留言,秒回數組
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; } } } } }