您是否曾经在网页上看到日历,并心想:“他们是怎么做到的?”对于这样的事情,使用插件甚至嵌入式 Google 日历是很自然的做法,但实际上,制作日历比您想象的要简单得多,只需要 HTML、CSS 和 JavaScript 三剑客即可。让我们一起动手制作一个吧!
我已经在 CodeSandbox 上设置了一个演示,您可以看到我们的目标。
查看演示 首先,让我们确定日历的一些需求。它应该:
- 显示指定月份的月份网格
- 显示前一个月和下一个月的日期,以便网格始终完整
- 指示当前日期
- 显示当前选定月份的名称
- 导航到前一个月和下一个月
- 允许用户单击一次即可返回到当前月份
哦,我们将把它构建为一个单页面应用程序,从 Day.js(一个超轻量级的实用程序库)获取日历日期。
为了简化操作,我们将避免选择特定的框架。对于此设置,我使用 Parcel 进行包管理,以便我可以使用 Babel 编写代码、捆绑代码以及管理项目中唯一一个依赖项。查看 CodeSandbox 上的 package.json 文件以了解详细信息。
第一步:从基本的标记和样式开始
让我们从创建日历的基本模板开始。这不需要任何花哨的东西。但它也应该在不使用表格的情况下完成。
我们可以将我们的标记概述为三层,其中包含:
- 日历标题部分。这将显示当前选定的月份以及负责在月份之间分页的元素。
- 日历网格标题部分。同样,我们不会使用表格,但这就像一个包含一周中各天的列表的表头。
- 日历网格。您知道的,当前月份的每一天,都以网格中的正方形表示。
让我们在一个名为 index.js 的文件中编写这个。这可以放在项目文件夹中的 src 文件夹内。我们确实会在项目根目录中有一个 index.html 文件来导入我们的工作,但主要的标记将位于 JavaScript 文件中。
document.getElementById("app").innerHTML = ` <div> <div> July 2020 </div> <div> Today > </div> <ol> <li>Mon</li> ... <li>Sun</li> </ol> <ol> <li> 1 ... 29 </li> </ol> </div> `;
让我们继续将此文件导入到位于项目根目录中的 index.html 文件中。这里没有什么特别的事情发生。它仅仅是 HTML 样板,其中包含一个由我们的应用程序定位并注册我们的 index.js 文件的元素。
<meta charset="UTF-8"> <title>Parcel Sandbox</title> <div id="app"></div> <script src="./src/index.js"></script>
现在我们有一些标记可以使用了,让我们稍微调整一下样式,以便我们有一个良好的视觉效果作为开始。具体来说,我们将:
- 使用 flexbox 定位元素
- 使用 CSS 网格创建日历框架
- 在单元格内定位标签
首先,让我们在与 index.js 相同的 src 文件夹中创建一个新的 styles.css 文件,并将此内容放入其中:
/* ... (CSS 代码同上) ... */
设置网格的关键部分是:
.day-of-week, .days-grid { /* 7 equal columns for weekdays and days cells */ display: grid; grid-template-columns: repeat(7, 1fr); }
请注意,日历网格标题和日历网格本身都使用 CSS 网格进行布局。我们知道一周总是有七天,因此这允许我们使用 repeat() 函数创建七个彼此成比例的列。我们还在每个日历日期上声明了一个 min-height 为 100px,以确保行保持一致。
我们需要将这些样式与标记连接起来,因此让我们将其添加到 index.js 文件的顶部:
import "./styles.css";
这是一个很好的停止点,看看我们到目前为止有什么。
查看演示 ### 第二步:设置当前月份日历
您可能已经注意到,该模板目前只包含静态数据。月份被硬编码为七月,日期数字也被硬编码了。这就是 Day.js 发挥作用的地方。它提供我们所需的所有数据,以便使用真实的日历数据将日期正确地放置在一周的正确日期中。它允许我们获取和设置从一个月开始日期到显示数据所需的所有日期格式选项的任何内容。
我们将:
- 获取当前月份
- 计算应放置日期的位置(工作日)
- 计算显示前一个月和下一个月的日期
- 将所有日期组合到一个数组中
首先,我们需要导入 Day.js 并删除所有静态 HTML(选定月份、工作日和日期)。我们将通过将此添加到 index.js 文件中导入样式的正上方来做到这一点:
import dayjs from "dayjs";
我们还将依靠 Day.js 插件来获得帮助。WeekDay 帮助我们设置一周的第一天。有些人喜欢将星期日作为一周的第一天。其他人更喜欢星期一。哎呀,在某些情况下,从星期五开始是有意义的。我们将从星期一开始。
weekOfYear 插件返回当年当前周的数字值。一年有 52 周,因此我们可以说从 1 月 1 日开始的那一周是一年的第一周,依此类推。
因此,这是我们在导入语句之后添加到 index.js 中的内容:
const weekday = require("dayjs/plugin/weekday"); const weekOfYear = require("dayjs/plugin/weekOfYear"); dayjs.extend(weekday); dayjs.extend(weekOfYear);
一旦我们剥离了硬编码的日历值,这就是我们到目前为止在 index.js 中的内容:
// ... (JavaScript 代码同上) ...
现在让我们设置一些常量。具体来说,我们想构造一个一周中各天(即星期一、星期二、星期三等)的数组:
// ... (JavaScript 代码同上) ...
然后,我们想获取当前年份并以 YYYY 格式设置它:
// ... (JavaScript 代码同上) ...
我们想将当前月份设置为加载日历时的起点,其中 M 将月份格式化为数值(例如,一月等于 1):
// ... (JavaScript 代码同上) ...
让我们继续使用一周中的各天填充我们的日历网格标题。首先,我们获取正确的元素(#days-of-week),然后我们遍历 WEEKDAYS 数组,为数组中的每个项目创建一个列表项元素,同时设置每个项目的名称:
// ... (JavaScript 代码同上) ...
第三步:创建日历网格
这非常简单,但现在真正的乐趣开始了,因为我们现在将使用日历网格。让我们停下来思考一下,为了正确地做到这一点,我们真正需要做什么。
首先,我们希望日期数字落在正确的工作日列中。例如,2020 年 7 月 1 日是星期三。这就是日期编号应该开始的地方。
如果一个月的第一天是星期三,那么这意味着第一周的星期一和星期二将有空的网格项目。这个月的最后一天是 7 月 31 日,是星期五。这意味着最后一周的星期六和星期日将是空的。我们想用前一个月和下一个月的尾随日期和前导日期填充这些日期,以便日历网格始终完整。
创建当前月份的日期
要将当前月份的日期添加到网格,我们需要知道当前月份有多少天。我们可以使用 Day.js 提供的 daysInMonth 方法来获取它。让我们为此创建一个辅助方法。
// ... (JavaScript 代码同上) ...
当我们知道这一点时,我们创建一个长度等于当前月份天数的空数组。然后我们映射()该数组并为每个数组创建一个日期对象。我们创建的对象具有任意结构,因此如果需要,您可以添加其他属性。
在这个例子中,我们需要一个 date 属性,该属性将用于检查特定日期是否为当前日期。我们还将返回一个 dayOfMonth 属性,该属性充当标签(例如 1、2、3 等)。isCurrentMonth 检查日期是否在当前月份内或其外部。如果它在当前月份之外,我们将对其进行样式设置,以便人们知道它们在当前月份的范围之外。
// ... (JavaScript 代码同上) ...
将前一个月的日期添加到日历网格
要获取前一个月的日期以在当前月份中显示,我们需要检查选定月份的第一天是星期几。这就是我们可以使用 Day.js 的 WeekDay 插件的地方。让我们为此创建一个辅助方法。
// ... (JavaScript 代码同上) ...
然后,基于此,我们需要检查前一个月中的最后一个星期一是哪一天。我们需要这个值来知道当前月份视图中应该显示前一个月多少天。我们可以通过从当前月份的第一天减去工作日的值来获得它。例如,如果一个月的第一天是星期三,我们需要减去 3 天才能获得前一个月的最后一个星期一。有了这个值,我们就可以创建一个日期对象数组,从前一个月的最后一个星期一开始,一直到那个月的最后一天。
// ... (JavaScript 代码同上) ...
将下一个月的日期添加到日历网格
现在,让我们反过来计算我们需要从下一个月中获取哪些日期来填充当前月份的网格。幸运的是,我们可以使用我们刚刚为前一个月计算创建的相同辅助方法。不同之处在于,我们将通过从 7 减去该工作日数值来计算下一个月中应该显示多少天。
因此,例如,如果一个月的最后一天是星期六,我们需要从 7 减去 1 天来构造从下一个月(星期日)开始所需的日期数组。
// ... (JavaScript 代码同上) ...
好的,我们知道如何创建所有所需的天数,让我们使用我们刚刚创建的方法,然后将所有天数合并到一个包含我们想要在当前月份显示的所有天数的单个数组中,包括前一个月和下一个月的填充日期。
// ... (JavaScript 代码同上) ...
这是我们在 index.js 中组合在一起的所有内容:
// ... (JavaScript 代码同上) ...
查看演示 ### 第四步:显示日历日期
好的,所以我们有日历的基本标记,我们需要显示当前月份日期的数据,加上前一个月和下一个月的日期以填充空的网格项目。现在我们需要将日期附加到日历!
我们已经有一个日历网格的容器 #calendar-days。让我们获取该元素。
// ... (JavaScript 代码同上) ...
现在,让我们创建一个将日期附加到日历视图的功能。
// ... (JavaScript 代码同上) ...
请注意,我们正在对来自前一个月和下一个月的日期进行检查,以便我们可以添加一个类来将它们与当前月份的日期区分开来:
// ... (CSS 代码同上) ...
就是这样!我们的日历现在应该按照我们想要的方式显示了。
查看演示 ### 第五步:选择当前月份
我们到目前为止所拥有的非常不错,但是我们希望用户能够向前和向后分页月份,从当前月份开始。我们已经拥有大部分逻辑,所以我们真正需要做的就是向分页按钮添加一个点击侦听器,该侦听器重新运行日期计算并使用更新的数据重新绘制日历。
在我们开始之前,让我们定义当前月份、前一个月和下一个月份的日期变量,以便我们可以在整个代码中引用它们。
// ... (JavaScript 代码同上) ...
现在,让我们创建一个方法,该方法将负责在分页到另一个月份时重新计算日历日期并重新渲染日历。我们将调用该函数 createCalendar。此方法将接受两个属性——年份和月份——并且基于此,日历将使用新数据重新渲染,而无需重新加载页面。
该方法将替换标题内容以始终显示选定的月份标签。
// ... (JavaScript 代码同上) ...
然后它将获取日历日期容器并删除所有现有日期。
// ... (JavaScript 代码同上) ...
清除日历后,它将使用我们之前创建的方法计算应该显示的新日期。
// ... (JavaScript 代码同上) ...
最后,它将为每一天附加一个日期元素。
// ... (JavaScript 代码同上) ...
还缺少一个逻辑部分:一个 removeAllDayElements 方法,用于清除现有的日历。此方法获取第一个日历日期元素,将其删除,并将其替换为另一个元素。从那里开始,它将循环运行逻辑,直到删除所有元素。
// ... (JavaScript 代码同上) ...
现在,当我们想要更改月份时,我们可以重用该逻辑。回想一下第一步,当时我们为组件创建了一个静态模板。我们添加了这些元素:
// ... (HTML 代码同上) ...
这些是月份之间分页的控件。要更改它,我们需要存储当前选定的月份。让我们创建一个变量来跟踪它是什么,并将其初始值设置为本月。
// ... (JavaScript 代码同上) ...
现在,为了使选择器工作,我们需要一些 JavaScript。为了使其更易于阅读,我们将创建另一个名为 initMonthSelectors 的方法,并将逻辑保留在那里。此方法将向选择器元素添加事件侦听器。它将侦听点击事件并将 selectedMonth 的值更新为新选定月份的名称,然后使用正确的年份和月份值运行 createCalendar 方法。
// ... (JavaScript 代码同上) ...
就是这样!我们的日历准备好了。虽然这很好,但如果我们可以标记当前日期以便它从其余日期中脱颖而出,那就更好了。这应该不难。我们已经在设置当前月份之外的日期样式,所以让我们做类似的事情。
我们将创建一个设置为今天的变量:
// ... (JavaScript 代码同上) ...
然后,在 appendDay 方法中,我们在应用当前月份之外日期的类时,必须添加另一个检查以查看该元素是否为今天的日期。如果是,我们将向该元素添加一个类:
// ... (JavaScript 代码同上) ...
现在我们可以设置样式了!
// ... (CSS 代码同上) ...
瞧,我们完成了!查看最终演示以查看所有内容的组合。
查看演示
以上是如何使用真实数据进行每月日历的详细内容。更多信息请关注PHP中文网其他相关文章!

盖茨比(Gatsby)进行了出色的处理和处理图像。例如,它可以帮助您节省图像优化的时间,因为您不必手动

您知道如何(在某种程度上)使用::选择的文本样式?好吧,杰夫·斯塔尔(Jeff Starr)发现了一个怪异的CSS错误。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

WebStorm Mac版
好用的JavaScript开发工具

记事本++7.3.1
好用且免费的代码编辑器

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。