打造超酷的 React 迷你日历组件,只需几步!

你好,我是小白Coding日志,一个热爱技术的程序员。在这里,我分享自己在编程和技术世界中的学习心得和体会。希望我的文章能够给你带来一些灵感和帮助。欢迎来到我的博客,一起在技术的世界里探索前行吧!

前言

现在市面上的组件库大多包含日历组件,那么它们具体是如何实现的呢?其实原理很简单,主要是通过使用Date对象的相关API。今天我们就来开发一个迷你版的日历组件。

功能分析

实现一个迷你版的日历组件页面布局:
  1. Header部分:最中间的位置用于显示当前月份,左右两边分别设置切换上月和下月的按钮。
  2. 星期显示:Header的下方依次显示星期日到星期六。
  3. Body部分:显示当前月的天数。可以根据当前月份获取这个月有多少天,以及根据当前月1号获取是星期几,这样我们就能知道这个月从哪一天开始。

为日历组件提供默认值,即当前日历组件默认渲染为当前年份和月份。此外,还需提供一个onChange方法,用于返回当前选中的日期。这样,一个基本的日历组件就完成了。

项目搭建

使用vite来创建一个React项目

npm create vite@latest calendar-mini

选择React然后选择JavaScript

image.png
切换到项目目录下cd calendar-mini,运行npm install 安装依赖,npm run dev 把项目跑起来
image.png

编码

  1. 页面基本布局

删除App.jsx中App组件中的HTML内容只保留下h1标签,

import { useState } from 'react'
import './App.css'function App() {const [count, setCount] = useState(0)return (<><h1>mini日历组件📅</h1></>)
}export default App

新增一个Calendar组并提供基本样式,在App.jsx中导入组件

import React from 'react';function Calendar() {return (<div className="calendar"><div className="header"><button>&lt;</button><div>20237</div><button>&gt;</button></div><div className="days"><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="empty"></div><div className="empty"></div><div className="day">1</div><div className="day">2</div><div className="day">3</div><div className="day">4</div><div className="day">5</div><div className="day">6</div><div className="day">7</div><div className="day">8</div><div className="day">9</div><div className="day">10</div><div className="day">11</div><div className="day">12</div><div className="day">13</div><div className="day">14</div><div className="day">15</div><div className="day">16</div><div className="day">17</div><div className="day">18</div><div className="day">19</div><div className="day">20</div><div className="day">21</div><div className="day">22</div><div className="day">23</div><div className="day">24</div><div className="day">25</div><div className="day">26</div><div className="day">27</div><div className="day">28</div><div className="day">29</div><div className="day">30</div><div className="day">31</div></div></div>);
}export default Calendar;
.calendar {border: 1px solid #aaa;padding: 10px;width: 300px;height: 250px;
}.header {display: flex;justify-content: space-between;align-items: center;height: 40px;
}.days {display: flex;flex-wrap: wrap;
}.empty, .day {width: calc(100% / 7);text-align: center;line-height: 30px;
}.day:hover {background-color: #ccc;cursor: pointer;
}
.day:hover, .selected {background-color: #22a4f1;cursor: pointer;
}
.m-10 {margin: 10px 0;
}
import { useState } from 'react'
import './App.css'
import Calendar from './component/Calendar'
function App() {return (<><h1>mini日历组件📅</h1><Calendar /></>)
}export default App

来看看效果👇
image.png

  1. 根据当前月份获取上月下月

结合useState来获取日历组件的当前年份和月份,月份要加1因为月份是从0开始的image.png
根据当前月获取上月下月

// 上月 const lastMonth = () =>{setDate(new Date(date.getFullYear(), date.getMonth() - 1, 1))}// 下月const nextMonth = () =>{setDate(new Date(date.getFullYear(), date.getMonth() + 1, 1))}
  1. 根据当前月份来渲染日期
 const renderDays = () => {const days = []const daysCount = daysOfMonth(date.getFullYear(), date.getMonth())const firstDays = firstDayOfMonth(date.getFullYear(), date.getMonth())for(let i = 0; i<firstDays; i++){days.push(<div key={`empty-${i}`} className="empty"></div>)}for(let i = 1; i<=daysCount; i++){const handelClick = () =>{const current = new Date(date.getFullYear(), date.getMonth(), i)setDate(current)props.onChange(current)}if(i === date.getDate()){days.push(<div key={i} className="day selected" onClick={()=>handelClick()}>{i}</div>)}else{days.push(<div key={i} className="day" onClick={()=>handelClick()}>{i}</div>)}}return days}

定义一个renderDays函数用来渲染日期,提供一个days数组来动态的渲染日期,daysCount是当前月的天数,firstDays是当前月是从星期几开始的,先循环firstDays来添加空白项,再循环daysCount添加天,handelClick当点击某一天的时候选中并改变背景色。

  1. 添加默认值defaultValue和onChange方法

Calendar组件提供默认值
image.png
为state设置默认值
image.png
Calendar组件提供onChange方法,在点击某一天的时候调用onChange回调将最新的值传递给onChange方法

image.png
image.png

Calendar.jsx组件全部代码

import { useState } from 'react';function Calendar(props) {const [date, setDate] = useState(new Date(props.defaultValue))console.log(date.toLocaleDateString())// 上月 const lastMonth = () =>{setDate(new Date(date.getFullYear(), date.getMonth() - 1, 1))}// 下月const nextMonth = () =>{setDate(new Date(date.getFullYear(), date.getMonth() + 1, 1))}
// 获取每个月有多少天
const daysOfMonth = (year, month) =>{return new Date(year, month + 1, 0).getDate()
}
// 获取每个月第一天是星期几
const firstDayOfMonth = (year, month) =>{return new Date(year, month, 1).getDay()
}
const renderDays = () => {const days = []const daysCount = daysOfMonth(date.getFullYear(), date.getMonth())const firstDays = firstDayOfMonth(date.getFullYear(), date.getMonth())for(let i = 0; i<firstDays; i++){days.push(<div key={`empty-${i}`} className="empty"></div>)}for(let i = 1; i<=daysCount; i++){const handelClick = () =>{const current = new Date(date.getFullYear(), date.getMonth(), i)setDate(current)props.onChange(current)}if(i === date.getDate()){days.push(<div key={i} className="day selected" onClick={()=>handelClick()}>{i}</div>)}else{days.push(<div key={i} className="day" onClick={()=>handelClick()}>{i}</div>)}}return days
}return (<div className="calendar"><div className="header"><button onClick={lastMonth}>&lt;</button><div>{ date.getFullYear() }{ date.getMonth() + 1 }</div><button onClick={nextMonth}>&gt;</button></div><div className="days"><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div><div className="day"></div>{renderDays()}</div></div>);
}export default Calendar;

App.jsx代码

import { useState } from 'react'
import './App.css'
import Calendar from './component/Calendar'
function App() {return (<><h1>mini日历组件📅</h1><Calendar defaultValue={'2024-07-19'} onChange={(date)=>{alert(date.toLocaleDateString())}} /><Calendar defaultValue={'2024-10-04'} /</>)
}export default App

bandicam-2024-07-19-00-32-19-886.gif
以上就实现了一个mini版的日历组件😁
最后还是那句话:即使代码逻辑很简单,也值得记录下来。我的编程目标是避免重复造轮子!😊
如果觉得有用,就给我点个赞吧😁
探索更多有趣知识,欢迎关注我的微信公众号:小白Coding日志,每天分享精彩内容,与你一同探寻知识的边界。一起开启知识新旅程!🚀📚
关注我的技术博客,探索前沿科技与实用开发技巧。一起携手走向代码的精彩世界!🚀💻 不错过每一篇精彩!

https://www.xiaobaicoding.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3250448.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

基于Linux的USB-wifi配置流程

目录 内核配置 配置 CFG80211 配置usb 配置 Netlink 配置DHCP 工作流程 1.连接到无线网络 2.设置网络接口&#xff1a; 3.验证连接&#xff1a; 4. 接收数据&#xff1a; 最近daisy一直忙活这个linux的wifi驱动和bluze蓝牙驱动&#xff0c;相比较蓝牙&#xff0c;WiFi的驱动和内…

面对垃圾邮件的骚扰,U-Mail邮件安全网关来帮你

在近几年的时间里&#xff0c;企业面临垃圾邮件的威胁成指数级增长&#xff0c;据第三方统计&#xff0c;垃圾邮件占电子邮件总通讯量的60%以上。与此同时&#xff0c;垃圾邮件的类型以及发送手段也愈加复杂化、多样化&#xff0c;电子邮件也一跃成为病毒或恶意软件的主要传播渠…

金蝶官宣:法大大电子签章“星空旗舰版”来了!

融合了数字签名、实名认证、AI、区块链、大数据等能力的法大大电子签章“星空旗舰版”来了&#xff01;通过与金蝶云星空旗舰版的集成产品打造&#xff0c;法大大携手金蝶共同面向客户提供高质量的产品综合解决方案服务。以下内容转载自金蝶云生态&#xff1a; 产品与解决方案 …

kkfileView

目录 一、基本特性 二、安装与部署 三、项目接入使用 四、项目地址与文档 五、应用场景 六、前端使用 kkFileView是一个基于Spring Boot框架构建的文件文档在线预览解决方案&#xff0c;它提供了广泛的文件类型支持、易部署性、跨平台服务、二次开发友好等多种特性。以下是对…

Nginx(详解)

1. 什么是Nginx&#xff1f; Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;在BSD-like 协议下发行。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务器中表…

“点点通“餐饮点餐小程序-计算机毕业设计源码11264

"点点通"餐饮点餐小程序 XXX专业XX级XX班&#xff1a;XXX 指导教师&#xff1a;XXX 摘要 随着中国经济的飞速增长&#xff0c;消费者的智能化水平不断提高&#xff0c;许多智能手机和相关的软件正在得到更多的关注和支持。其中&#xff0c;微信的餐饮点餐小程序更…

C#知识|账号管理系统-账号信息管理界面[1]:账号分类选择框、Panel面板设置

哈喽,你好啊,我是雷工! 前一节实现了多条件查询后端代码的编写, 接下来继续学习账号信息管理界面的功能编写,本节主要记录账号分类选择框和Panel的设置, 以下为学习笔记。 01 功能说明 本节实现以下功能: ①:账号分类选择框只能选择,无法自由输入; ②:账号分类框默认…

11款常用的Python虚拟环境管理器,最受推崇的居然是最后一个

文章目录 1. venv2. virtualenv3. Pipenv4. pyenv5. Conda6. Poetry7. PDM8. Huak9. Pixi10. Rye11. uv《Python从入门到精通&#xff08;第3版&#xff09;&#xff08;软件开发视频大讲堂&#xff09;》编辑推荐内容简介作者简介目录 以下文章来源于Python学研大本营 &#x…

Elasticsearch:如何选择向量数据库?

作者&#xff1a;来自 Elastic Elastic Platform Team 向量数据库领域是一个快速发展的领域&#xff0c;它正在改变我们管理和搜索数据的方式。与传统数据库不同&#xff0c;向量数据库以向量的形式存储和管理数据。这种独特的方法可以实现更精确、更相关的搜索&#xff0c;并允…

ROS2从入门到精通2-3:详解机器人3D物理仿真Gazebo与案例分析

目录 0 专栏介绍1 什么是Gazebo?2 Gazebo架构2.1 Gazebo前后端2.2 Gazebo文件格式2.3 Gazebo环境变量3 Gazebo安装与基本界面4 搭建自己的地图4.1 编辑地图4.2 保存地图4.3 加载地图5 常见问题0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有…

Java面试八股之Redis怎么实现消息队列

Redis怎么实现消息队列 Redis实现消息队列主要依赖于其内置的数据结构&#xff0c;如List、Pub/Sub&#xff08;发布/订阅&#xff09;和Stream。下面将分别介绍这三种方式及其特点&#xff1a; 1. List实现消息队列 Redis的List是一个双向链表&#xff0c;支持快速的头部和…

ARM架构(二)—— arm v7/v8/v9寄存器介绍

1、ARM v7寄存器 1.1 通用寄存器 V7 V8开始 FIQ个IRQ优先级一样&#xff0c; 通用寄存器&#xff1a;31个 1.2 程序状态寄存器 CPSR是程序状态毒存器&#xff0c;保存条件标志位&#xff0c;中断禁止位&#xff0c;当前处理器模式等控制和状态位。每种异常模式下还存在SPSR&…

Unity扩展SVN命令

可以直接在unity里右键文件提交和查看提交记录 顶部菜单栏上回退和更新整个unity工程 SvnForUnity.CS 记得要放在Editor文件夹下 using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using UnityEditor; using Unity…

互联网行业的产品方向(二)

数字与策略产品 大数据时代&#xff0c;数据的价值越来越重要。大多数公司开始对内外全部数据进行管理与挖掘&#xff0c;将业务数据化&#xff0c;数据资产化&#xff0c;资产业务化&#xff0c;将数据产品赋能业务&#xff0c;通过数据驱动公司业务发展&#xff0c;支撑公司战…

PyTorch使用细节

model.eval() &#xff1a;让BatchNorm、Dropout等失效&#xff1b; with torch.no_grad() &#xff1a; 不再缓存activation&#xff0c;节省显存&#xff1b; 这是矩阵乘法&#xff1a; y1 tensor tensor.T y2 tensor.matmul(tensor.T)y3 torch.rand_like(y1) torch.matm…

19_Shell练习题

19_Shell练习题 一、获取并打印空行行号 awk /^$/{print NR} test.txt二、求一列的和 awk -v sum0 { sum$2 } END{ print sum } test.txt三、检查文件是否存在 #!/bin/bashecho "请输入要查询文件的全路径名称&#xff1a;" read -p "例如&#xff1a;/temp…

(MLLMs)多模态大模型论文分享(1)

Multimodal Large Language Models: A Survey 摘要&#xff1a;多模态语言模型的探索集成了多种数据类型&#xff0c;如图像、文本、语言、音频和其他异构性。虽然最新的大型语言模型在基于文本的任务中表现出色&#xff0c;但它们往往难以理解和处理其他数据类型。多模态模型…

Volatility:分析MS10-061攻击

1、概述 # 1&#xff09;什么是 Volatility Volatility是开源的Windows&#xff0c;Linux&#xff0c;MaC&#xff0c;Android的内存取证分析工具。基于Python开发而成&#xff0c;可以分析内存中的各种数据。Volatility支持对32位或64位Wnidows、Linux、Mac、Android操作系统…

AI算不出9.11和9.9哪个大?六家大模型厂商总结了这些原因

大模型“答对”或“答错”其实是个概率问题。关于“9.11和9.9哪个大”&#xff0c;这样一道小学生难度的数学题难倒了一众海内外AI大模型。7月17日&#xff0c;第一财经报道了国内外“12个大模型8个都会答错”这道题的现象&#xff0c;大模型的数学能力引发讨论。 “从技术人员…

《系统架构设计师教程(第2版)》第12章-信息系统架构设计理论与实践-02-信息系统架构

文章目录 1. 概述1.1 信息系统架构&#xff08;ISA&#xff09;1.2 架构风格 2. 信息系统架构分类2.1 信息系统物理结构2.1.1 集中式结构2.1.2 分布式结构 2.2 信息系统的逻辑结构1&#xff09;横向综合2&#xff09;纵向综合3&#xff09;纵横综合 3. 信息系统架构的一般原理4…