为了满足产品需求,在日历中可以添加排班信息,点击日期可以获取排班日期详细数据,自定义日历样式,并且支持手动折叠和展开,折叠时只显示当前周的日期,由于现有组件库修改起来比较麻烦,自己就手写了一个日历组件,下面是我代码及思路。
代码写的不好仅供参考,如有异议欢迎评论指正,感谢。
一个完整日历组价包括,标题年月,上个月和下个月,内容分为星期标题,'日', '一', '二', '三', '四', '五', '六',以及对应的日期排列。
日历每月日期生成排列
-
首先,通过
computed
函数创建一个计算属性days即每个月的日期
,这个属性的值会根据当前日期的变化而变化。 -
然后,获取当前日期信息,包括当前年份 (
year
)、当前月份 (month
)、当前日期 (currentDay
)。 -
获取今天的日期信息,包括今天的年份 (
todayYear
)、今天的月份 (todayMonth
)。 -
判断当前月份是否为当前年份的当月,并计算本月的天数 (
daysInMonth
)、上个月的天数 (daysInLastMonth
)、本月第一天是星期几 (firstDayOfMonth
)。 -
根据需要生成日历的显示数据:
- 如果当前月份是当前年份的当月,并且状态为折叠状态 (
state.isCollapsed
),则生成本月的一个部分日历,以当前日期所在的周为基准,从当前周的开始日到结束日。 - 否则,生成完整的一个月的日历。
- 如果当前月份是当前年份的当月,并且状态为折叠状态 (
-
对于生成的日历数据,如果是上个月的日期,设置
isLastMonth
为 true,如果是下个月的日期,设置isNextMonth
为 true,如果是当月的日期,设置isLastMonth
和isNextMonth
为 false。同时,判断该日期是否有课程安排 (isClassesDate
),并将日期、日期对应的数字、是否为上个月、是否为下个月、是否有课程安排等信息存入days
数组中。 -
最后返回生成的日期数据数组
days。
代码:
const days = computed(() => {
const today = new Date()
const year = currentDate.value.getFullYear()
const month = currentDate.value.getMonth()
const currentDay = currentDate.value.getDate()
const todayYear = today.getFullYear()
const todayMonth = today.getMonth()
const isCurrentMonth = year === todayYear && month === todayMonth
const daysInMonth = new Date(year, month + 1, 0).getDate()
const daysInLastMonth = new Date(year, month, 0).getDate()
const firstDayOfMonth = new Date(year, month, 1).getDay()
const days = []
let day = 1
let lastMonthDay = daysInLastMonth - firstDayOfMonth + 1
let nextMonthDay = 1
if (isCurrentMonth && state.isCollapsed) {
const todayDate = today.getDate()
const startOfWeek = todayDate - today.getDay() // 当前周的开始日
const endOfWeek = startOfWeek + 6 // 当前周的结束日
for (let day = startOfWeek; day <= endOfWeek; day++) {
const date = new Date(year, month, day)
let isClassesDate = props.isClassesDataList.some(
(item) => item.classesDate === dayjs(date).format('YYYY-MM-DD') && item.isClasses
)
days.push({ date, day: date.getDate(), isLastMonth: false, isNextMonth: false, isClassesDate })
}
} else {
for (let i = 0; i < 5 * 7; i++) {
if (i < firstDayOfMonth) {
days.push({
date: new Date(year, month - 1, lastMonthDay),
day: lastMonthDay,
isLastMonth: true,
isNextMonth: false,
isClassesDate: false
})
lastMonthDay++
} else if (i >= firstDayOfMonth + daysInMonth) {
days.push({
date: new Date(year, month + 1, nextMonthDay),
day: nextMonthDay,
isLastMonth: false,
isNextMonth: true,
isClassesDate: false
})
nextMonthDay++
} else {
const date = new Date(year, month, day)
// dayjs().format('YYYY-MM-DD')
// console.log(date, 'datedatedate')
// days.push({ date, day, isLastMonth: false, isNextMonth: false })
let isClassesDate = props.isClassesDataList.some(