使用 Tailwind 和 date-fns 构建日历组件
日历组件是网络上最常用、最有用的组件之一。它可以用来显示事件、安排提醒以及用于许多其他不同的用途。
过去几天,我一直在深入研究 Tailwind CSS,我想尝试构建一些在网络上更常用的东西。
在本文中,我们将使用Tailwind(一个流行的实用型 CSS 框架)和date-fns(一个流行的 JavaScript 日期和时间操作库)构建一个简单的日历组件。
本文将要构建的日历组件将具有以下功能:
- 默认显示当前月份
- 下个月
- 获取上个月
- 今日亮点
那么,让我们直接进入正题吧!
安装
我假设您已经搭建了一个基本的 React 项目。您可以按照Tailwind 官网安装部分提供的不同指南来安装 Tailwind CSS。
现在我们已经搭建了一个基本React + Tailwind项目,接下来让我们安装date-fns库。
如果您正在使用,npm请运行npm install date-fns命令安装软件包。如果您正在使用,yarn请运行yarn add date-fns命令。
现在我们已经安装了构建此组件所需的一切。
构建组件
让我们开始构建这个组件。
首先,我们将编写代码来显示当前月份和年份。我们还会添加按钮来切换上个月和下个月。以下是我们第一部分要构建的内容。
我使用heroicons(也是 Tailwind CSS 的开发者创建的)来创建用于获取上个月和下个月数据的按钮。
以下是用于渲染日历组件控件 UI 的 JSX 代码。
<div className="flex items-center justify-between">
<p className="font-semibold text-xl"> {format(firstDayOfMonth, "MMMM yyyy")} </p>
<div className="flex items-center justify-evenly gap-6 sm:gap-12">
<ChevronLeftIcon className="w-6 h-6 cursor-pointer" onClick={getPrevMonth} />
<ChevronRightIcon className="w-6 h-6 cursor-pointer" onClick={getNextMonth} />
</div>
</div>
以下是我们需要为这部分设置的功能和状态。
const today = startOfToday();
const [currMonth, setCurrMonth] = useState(() => format(today, "MMM-yyyy"));
let firstDayOfMonth = parse(currMonth, "MMM-yyyy", new Date());
const daysInMonth = eachDayOfInterval({
start: firstDayOfMonth,
end: endOfMonth(firstDayOfMonth),
});
const getPrevMonth = (event: React.MouseEvent<SVGSVGElement>) => {
event.preventDefault();
const firstDayOfPrevMonth = add(firstDayOfMonth, { months: -1 });
setCurrMonth(format(firstDayOfPrevMonth, "MMM-yyyy"));
};
const getNextMonth = (event: React.MouseEvent<SVGSVGElement>) => {
event.preventDefault();
const firstDayOfNextMonth = add(firstDayOfMonth, { months: 1 });
setCurrMonth(format(firstDayOfNextMonth, "MMM-yyyy"));
};
让我们来理解一下上面代码中的各个函数。
format该函数由库提供date-fns,主要用于格式化给定的日期,并返回格式化后的日期字符串。startOfToday该函数也由另一个函数提供date-fns,它会返回当前日期。parse该函数date-fns用于从给定的日期字符串中解析日期。eachDayOfInterval该函数date-fns返回指定日期范围内的日期数组。getPrevMonth该函数用于获取上个月的日期。它使用add`from` 函数date-fns,我们将其设置month为 `-1to` 以获取上个月的第一天。获取上个月的第一天后,我们可以重新计算并使用eachDayOfInterval该函数获取日期。getNextMonth该函数与之前类似,只是我们将值getPrevMonth设置为获取下个月的第一天。month1
如果你一直跟着教程,应该已经注意到我们将当月的所有日期存储在一个daysInMonth变量中。现在,我们将使用这个日期数组来渲染日历组件的用户界面。
在编写日历组件的代码之前,我们先编写一段代码来显示日历标题,其中将渲染日期名称。
这就是我们要渲染的内容。
以下是渲染上述用户界面的 JSX 代码。
首先,我们需要一个包含所有日期的数组。
const days = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
<div className="grid grid-cols-7 gap-6 sm:gap-12 place-items-center">
{
days.map((day, idx) => {
return (
<div key={idx} className="font-semibold">
{capitalizeFirstLetter(day)}
</div>
);
})}
</div>
现在日历标题已经渲染完成,我们可以继续编写代码,以网格格式显示所有日期。我们已经知道daysInMonth需要按月显示日期。
<div className="grid grid-cols-7 gap-6 sm:gap-12 mt-8 place-items-center">
{daysInMonth.map((day, idx) => {
return (
<div key={idx} className={colStartClasses[getDay(day)]}>
<p
className={`cursor-pointer flex items-center justify-center font-semibold h-8 w-8 rounded-full hover:text-white ${
isSameMonth(day, today) ? "text-gray-900" : "text-gray-400"
} ${!isToday(day) && "hover:bg-blue-500"} ${
isToday(day) && "bg-red-500 text-white"
}`}
>
{format(day, "d")}
</p>
</div>
);
})}
</div>;
在上面的代码中,
isToday该函数date-fns用于检查给定的日期是否为当前日期。isSameMonth该函数date-fns用于检查给定的日期是否属于同一月份。
const colStartClasses = [
"",
"col-start-2",
"col-start-3",
"col-start-4",
"col-start-5",
"col-start-6",
"col-start-7",
];
默认情况下,每月的第一天将显示在第一列第一行。以上代码将确保每个日期都显示在正确的日期列中。
以上代码将渲染以下用户界面。
如您所见,我们根据条件应用不同的类来突出显示当前日期并更改其他日期的文本颜色。
太长不看
这样,我们就可以使用 Tailwind CSS 和 date-fns 创建一个简单的日历组件。你可以在我的 GitHub 上查看最终版本的代码(链接在此)。
感谢您阅读本文!
文章来源:https://dev.to/vivekalhat/building-a-calendar-component-with-tailwind-and-date-fns-2c0i
