开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
一、前言
最近项目需要实现一个交易日历,没有很好的组件直接使用,于是就自己实现了下,大概样子如下图所示
二、核心实现
我们可以分为三部分来看:
- 头部:可以选择年份、月份、上下月份切换(和下面核心)
- 周:比较简单定义个数组
const CALENDAR_WEEKS = ['日', '一', '二', '三', '四', '五', '六']
- 核心日期怎么摆放,下面我们着重分析这个
- 首先我们知道每个月多少天,唯一一个有变动的就是闰年二月,所以我们可以先定义每月天数的数组,二月加个判断
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
// 对闰年二月天数处理
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
daysInMonth[1] = 29
}
- 然后我们通过
getDay()确定每月第一天,最后一条在周几,然后我们就可以知道上月、下月在当前日历需要显示几天;然后把上月、当月、下月日子合并一个数组去渲染。
核心代码
export const getAllDaysForYear = year => {
/**
* monthData 每月数据 用于最后输出
* daysInMonth 每个月的天数
* specialDaysInMonth 每个月第一天和最后一天的星期
*/
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
// 对闰年二月天数特殊处理
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
daysInMonth[1] = 29
}
const monthData = new Array(12).fill(null)
// eslint-disable-next-line
const specialDaysInMonth = monthData.slice(0).map((m, i) => {
return [new Date(year, i, 1).getDay(), new Date(year, i, daysInMonth[i]).getDay()]
})
// eslint-disable-next-line
return monthData.map((m, i) => {
const month = []
const pre = preDaysCreator(daysInMonth[i === 0 ? 11 : i - 1], specialDaysInMonth[i][0])
const normal = normalDaysCreator(daysInMonth[i])
const next = nextDaysCreator(specialDaysInMonth[i][1])
return month.concat(pre, normal, next)
})
}
const nextDaysCreator = lastDay => {
const nextDays = []
const count = 6 - lastDay
for (let i = 0; i < count; i++) {
const obj = {
content: i + 1,
type: 'next',
}
nextDays.push(obj)
}
return nextDays
}
const preDaysCreator = (preLastDay, firstDay) => {
const preDays = []
for (; firstDay > 0; firstDay--) {
const obj = {
content: preLastDay--,
type: 'pre',
}
preDays.splice(0, 0, obj)
}
return preDays
}
const normalDaysCreator = days => {
const normalDays = []
for (let i = 0; i < days; i++) {
const obj = {
content: i + 1,
type: 'cur',
}
normalDays.push(obj)
}
return normalDays
}
注意:getDay() 方法可返回一周(0~6)的某一天的数字;星期天为 0, 星期一为 1, 以此类推。
如果你页面不是从周日开始摆放,注意处理上月、下月方法循环的判断就好。