带任务显示的日历功能

发布于:2025-04-07 ⋅ 阅读:(29) ⋅ 点赞:(0)

引言

在 Web 开发中,日历组件是一个常见且实用的功能,它不仅能方便用户查看日期,还能结合任务安排,让用户清晰地了解每个日期对应的任务。本文将详细介绍如何使用 JavaScript 实现一个带任务显示的日历,同时结合 sessionStorage 存储任务数据,通过点击按钮实现月份切换和返回今日等功能。

功能概述

我们要实现的日历具有以下功能:

  1. 显示当前月份的日历,包括上个月的部分日期和本月的所有日期。
  2. 标记当前日期,使其与其他日期区分开来。
  3. 根据 sessionStorage 中存储的任务数据,在相应日期上显示任务信息,包括任务开始、进行中和结束的状态。
  4. 提供切换到上一个月、下一个月和返回今日的功能。

项目效果:

代码实现步骤

(一)HTML 结构搭建

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <link rel="stylesheet" href="./css/日历.css" />
    </head>
    <body>
        <div id="top_box">
            <span class="font">321321</span>
            <div class="left">
                <div class="left_arrow" onclick="last()">
                    <img src="./img/prev.png" alt="" />
                </div>
            </div>
            <div class="right">
                <div id="today" onclick="today()">今天</div>
                <div class="right_arrow" onclick="next()"><img src="./img/right.png" alt="" /></div>
            </div>
        </div>

        <div id="box">
            <div class="table_head">
                <div class="columns">周一</div>
                <div class="columns">周二</div>
                <div class="columns">周三</div>
                <div class="columns">周四</div>
                <div class="columns">周五</div>
                <div class="columns">周六</div>
                <div class="columns">周日</div>
            </div>
            <div id="content"></div>
        </div>

        <script src="js/日历.js"></script>
    </body>
</html>
详细解释
  • 顶部导航栏(#top_box:这部分是整个日历的控制区域,包含了几个重要的元素。span.font 用于显示当前月份的标题,让用户明确当前查看的时间范围。div.left 中的 div.left_arrow 是切换到上一个月的按钮,通过点击该按钮,用户可以查看上一个月的日历。div.right 包含了两个按钮,div#today 用于返回今日,点击后日历会显示当前日期所在的月份;div.right_arrow 则是切换到下一个月的按钮,方便用户查看未来月份的日历。
  • 日历表格头部(.table_head:该区域显示了一周七天的名称,即周一到周日,为用户提供了清晰的日期参照。
  • 日历内容区域(#content:这是日历的核心显示区域,用于动态显示日历的日期以及对应的任务信息。后续的 JavaScript 代码会将生成的 HTML 内容插入到这个区域中。

(二)JavaScript 逻辑实现

1. 初始化和数据存储
// 获取当前日期
let now = new Date();
render();
// 将数据存储到 sessionStorage 中
sessionStorage.setItem('data',
    '[{"title":"任务分割","start":"2025-04-15","end":"2025-04-31"},{"title":"1111","start":"2025-01-18","end":"2025-01-20"},{"title":"任务222222分割","start":"2025-01-21","end":"2025-01-31"},{"title":"任务3333333分割","start":"2025-01-25","end":"2025-01-31"}]'
);
详细解释
  • let now = new Date();:创建一个 Date 对象,获取当前的日期和时间。这个对象将作为后续日期计算和显示的基础。
  • render();:调用 render 函数,开始进行日历的渲染操作,将当前月份的日历和任务信息显示在页面上。
  • sessionStorage.setItem('data', ...):使用 sessionStorage 来存储任务数据。sessionStorage 是 HTML5 新增的一个会话存储对象,它允许在浏览器会话期间临时保存数据。这里将一个包含多个任务信息的 JSON 字符串存储在 data 键下,每个任务信息包含任务标题、开始日期和结束日期。
2. 日历渲染函数 render
function render() {
    //获取到上面存的数据
    let data = JSON.parse(sessionStorage.getItem('data'));
    console.log(data);
    // 获取月
    let year = now.getFullYear();
    // 获取年
    let month = now.getMonth() + 1;
    // 获取当前月的总天数
    let self_dates = new Date(year, month, 0).getDate();
    // 获取当前月第一天是星期几
    let firstDay = new Date(`${year}-${month}-1`).getDay();
    // 生成标题字符串
    let date_str = `${month}月 ${year}`;
    // 生成好的字符串更新到标题容器中
    document.getElementsByClassName('font')[0].innerHTML = date_str;
    let str = '';
    // 如果当前月第一天不是周一的话
    if (firstDay != 1) {
        // 获取上个月的月份
        let last_month = now.getMonth() - 1 < 0 ? 12 : now.getMonth() + 1;
        // 获取上一个月的年份
        let last_year = month == 1 ? year - 1 : year;
        // 获取上个月的总天数
        let last_dates = new Date(last_year, last_month, 0).getDate();
        //填充上一个月的日期
        for (let i = 0; i < firstDay - 1; i++) {
            str = `
                            <div class="items" style="color:gray;">
                                <div class="date">${last_dates}</div>
                            </div>
                        ` + str;
            last_dates--;
        }
    }
    // 填充当前月的日期
    for (let i = 0; i < self_dates; i++) {
        str += `<div class="items ${(function(){
                                let now = new Date();
                                if(now.getFullYear() == year && now.getMonth()+1 == month && now.getDate() == i+1){
                                    return 'light'
                                }else{
                                    return '';
                                }
                            }())}">
                                <div class="date">${i+1}</div>`;
        // 遍历数据
        for (let j in data) {
            // 获取数据开始的日期
            let start = +new Date(data[j].start);
            // 获取数据结束的日期
            let end = +new Date(data[j].end);
            // 获取当前的日期
            let nows = +new Date(`${year}-${month<10?'0'+month:month}-${i+1}`);
            console.log(start, data[j].start, nows, `${year}-${month}-${i+1}`, start == nows, j);
            // 如果现在是在开始和结束时间段内
            if (nows <= end && nows >= start) {
                // 如果现在是开始日期
                if (nows == start) {
                    str += `<div class="plan">${data[j].title}</div>`;
                    // 如果现在是结束日期
                } else if (nows == end) {
                    str += `<div class="plan">》》》》》</div>`;
                    //都不是的华
                } else {
                    str += `<div class="plan"></div>`;
                }
            }
        }
        str += `</div>`;
    }
    // 更新日历内容
    document.getElementById('content').innerHTML = str;
}
详细解释
  • 数据获取
    • let data = JSON.parse(sessionStorage.getItem('data'));:从 sessionStorage 中获取之前存储的任务数据,并使用 JSON.parse 方法将 JSON 字符串转换为 JavaScript 对象。
  • 日期信息计算
    • let year = now.getFullYear(); 和 let month = now.getMonth() + 1;:分别获取当前日期的年份和月份。需要注意的是,getMonth() 方法返回的月份是从 0 开始的,所以要加 1 才能得到实际的月份。
    • let self_dates = new Date(year, month, 0).getDate();:通过创建一个新的 Date 对象,传入年份、月份和 0 作为日期参数,获取当前月的总天数。因为传入 0 表示上个月的最后一天,所以可以得到当前月的总天数。
    • let firstDay = new Date(\({year}-\){month}-1).getDay();:创建一个表示当前月第一天的 Date 对象,并使用 getDay() 方法获取这一天是星期几。返回值 0 表示周日,1 表示周一,以此类推。
  • 标题更新
    • let date_str = ${month}月 ${year};:生成当前月份的标题字符串。
    • document.getElementsByClassName('font')[0].innerHTML = date_str;:将生成的标题字符串更新到页面上的 span.font 元素中。
  • 上个月日期填充
    • 如果当前月第一天不是周一,需要填充上个月的部分日期。通过计算上个月的月份和年份,获取上个月的总天数,然后使用循环生成 HTML 字符串,并将其添加到 str 变量的前面。这些日期的颜色设置为灰色,以与当前月的日期区分开来。
  • 当前月日期填充
    • 使用循环遍历当前月的每一天,生成对应的 HTML 元素。对于当前日期,通过一个立即执行函数判断是否为当前日期,如果是则添加 light 类,用于特殊标记。
    • 对于每一天,遍历任务数据,判断该日期是否在某个任务的开始和结束日期范围内。如果是,则根据具体情况显示任务标题、结束标识或空占位符。
  • 内容更新
    • document.getElementById('content').innerHTML = str;:将生成的 HTML 字符串插入到页面的 #content 元素中,完成日历的渲染。
3. 月份切换和返回今日功能
function next() {
    now.setMonth(now.getMonth() + 1);
    render();
}

function last() {
    now.setMonth(now.getMonth() - 1);
    render();
}

function today() {
    now = new Date();
    render();
}
详细解释
  • next 函数:将 now 对象的月份加 1,然后调用 render 函数重新渲染日历,实现切换到下一个月的功能。
  • last 函数:将 now 对象的月份减 1,再调用 render 函数重新渲染日历,实现切换到上一个月的功能。
  • today 函数:将 now 对象重置为当前日期,然后调用 render 函数重新渲染日历,实现返回今日的功能。

四、代码优化与拓展建议

  1. 数据动态加载:目前任务数据是硬编码在 sessionStorage 中的,可以将其改为从后端接口获取,实现数据的动态更新。例如,使用 fetch 或 XMLHttpRequest 发送请求,获取最新的任务数据。
  2. 样式优化:进一步优化日历的样式,添加更多的动画效果和交互反馈,提升用户体验。比如,在日期上添加鼠标悬停效果,显示更多的任务详情。
  3. 性能优化:当任务数据量较大时,频繁的 DOM 操作可能会影响性能。可以考虑使用虚拟列表等技术,减少不必要的 DOM 渲染。

五、总结

通过以上详细的代码实现和分析,我们成功使用 JavaScript 实现了一个功能丰富的带任务显示的日历。该日历不仅能够准确显示日期和任务信息,还提供了方便的交互操作,满足了用户在不同时间范围查看和管理任务的需求。在实际项目中,可以根据具体需求对代码进行进一步的优化和拓展,使其更加完善和实用。