发财日历 开发日志

[发财日历] 开发日志

前言

发财日历是一个由纯JS和CSS完成的一个小作品,主要是为了后面项目中作为一个组件复用

目前实现的功能有:

  1. 显示日程

  2. 日程标记

  3. 高亮今日

  4. 日期选择

链接

GitHub链接

预览链接

代码分析

整体代码结构

渲染加事件绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
let currentTime = new Date()

render(currentTime)

g('#prevMonth').onclick = () => {...}

g('#nextMonth').onclick = () => {...}

g('#today').onclick = () => {...}

function render(time) {...}

function g(selector) {...}

事件绑定

需要给每个日期添加click事件,为了优化性能,使用事件委托代替给每个日期添加监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
days.addEventListener('click', (e) => {
if (selectedLi) {
selectedLi.classList.remove('calender-days-selected')
}
e.target.classList.add('calender-days-selected')
selectedLi = e.target
if (e.target.classList.contains('calender-days-hasEvents')) {
const key = `${year}-${month}-${e.target.textContent}`
const events = window.data[key]
const eventFragment = document.createDocumentFragment()
events.map(event => {
const div = document.createElement('div')
div.classList.add('events-item')
div.textContent = event
eventFragment.append(div)
})
g('#events').innerHTML = ""
g('#events').append(eventFragment)
} else {
g('#events').innerHTML = "<div>无</div>"
}
})

避免频繁操作DOM

使用fragment,一次性装载所有日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function render(time) {
...
function generateDays(year, month) {
...
const fragment = document.createDocumentFragment()
...
days.addEventListener('click', (e) => {
...
if (...)) {
...
const eventFragment = document.createDocumentFragment()
events.map(event => {
const div = document.createElement('div')
...
eventFragment.append(div)
})
...
}
})
...
for (...) {
const li = document.createElement('li')
...
fragment.prepend(li)
}

for (...) {
const li = document.createElement('li')
...
fragment.append(li)
}

for (...) {
...
const li = document.createElement('li')
...
fragment.append(li)
}
days.append(fragment) //一次性装载
}
}

日程标记的实现

使用伪元素实现日程的绿色圆圈小标记

1
2
3
4
5
6
7
8
9
10
11
.calender-days > li.calender-days-hasEvents::after {
content: '';
border: 1px solid green;
position: absolute;
top: 4px;
right: 4px;
width: 8px;
height: 8px;
background: green;
border-radius: 50%;
}

日期计算逻辑

由于使用了原生JS,因此日期相关的API使用的也是原生的Date函数,比较难用

当月有多少天

下个月的月初 - 一天 = 当月的最后一天是几号 = 当月有多少天

1
2
3
const lastDayOfCurrentMonth = new Date(new Date(year, month - 1 + 1, 1) - 86400 * 1000)
const daysOfCurrentMonth = lastDayOfCurrentMonth.getDate()

周几如何计算

JS的getDay()是将周日作为0,周六作为6,因此为了更符合国人使用习惯,改成周一为1,周日为7

1
2
3
if (weekdayOfFirstDayOfCurrentMonth === 0) {
weekdayOfFirstDayOfCurrentMonth = 7
}

上、下个月如何计算

当前月的第一天 - 一天 = 将当前时间拨到上个月

1
2
3
4
g('#prevMonth').onclick = () => {
const firstDayOfCurrentMonth = new Date(currentTime.getFullYear(), currentTime.getMonth(), 1)
render(new Date(firstDayOfCurrentMonth - 86400 * 1000))
}

后记

简单的小组件,实现也很容易,主要作为后续项目的一个模块保存了下来,如果你有任何想法,欢迎留言告诉我~


发财日历 开发日志
https://bald3r.wang/2022/07/26/30-发财日历-开发日志/
作者
Allen
发布于
2022年7月26日
许可协议