概述
一個超級簡單的日歷,日歷核心代碼只有十幾行,方便以后擴展成日程管理。源碼點擊這里
前言
日歷或者日程管理,在項目中是個高頻使用的組件,經常會碰到日程管理這種需求,網上已經有很多成熟的庫,但是產品經理的思維是你我無法揣測的,所以先儲備一下,做個簡單的日歷,方便以后用的的時候直接用,代碼使用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;
}
}
}
}
}
