[发财日历] 开发日志

·  阅读 677

前言

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

目前实现的功能有:

  1. 显示日程
  2. 日程标记
  3. 高亮今日
  4. 日期选择

链接

GitHub链接

预览链接

代码分析

整体代码结构

渲染加事件绑定

let currentTime = new Date()

render(currentTime)

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

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

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

function render(time) {...}

function g(selector) {...}
复制代码

事件绑定

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

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,一次性装载所有日期

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)   //一次性装载
  }
}
复制代码

日程标记的实现

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

.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函数,比较难用

当月有多少天

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

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

复制代码

周几如何计算

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

if (weekdayOfFirstDayOfCurrentMonth === 0) {
      weekdayOfFirstDayOfCurrentMonth = 7
}
复制代码

上、下个月如何计算

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

g('#prevMonth').onclick = () => {
  const firstDayOfCurrentMonth = new Date(currentTime.getFullYear(), currentTime.getMonth(), 1)
  render(new Date(firstDayOfCurrentMonth - 86400 * 1000))
}
复制代码

后记

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

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改