前端练手案例之日历(原生)一
介绍
用原生三件套从零到一实现以下日历模块,样式如图
目前具备以下功能
- 展示当前年月日,并对当前日其展示激活状态
- 点击
上一月
下一月
进行跳转
完成骨架搭建
首先先对,整体样式进行构思(对于毫无艺术细胞的我来说,差点要了半条命),最后决定先按照上图先做着,后边要改再说,日期内容采用的是表格
进行渲染
<div id="calendar"><div class="head"><div class="pre-month">上一月</div><div class="date"><!-- 这里先用的是死数据 --><div class="year">2022</div><div class="month">10月</div></div><div class="next-month">下一月</div></div><div class="main"><table><thead><tr><!-- 表格关于周几的就直接写上不生成了 --><td>日</td><td>一</td><td>二</td><td>三</td><td>四</td><td>五</td><td>六</td></tr></thead><tbody></tbody></table></div></div>
添加样式
样式就按照上面那个不太好看的样式来就行,因为是表格,所以布局的内容比较少
#calendar {display: flex;flex-direction: column;width: 100vw;box-sizing: border-box;padding: 10px;margin: 26px auto;background-color: #f49bc4;}/* 标题部分 */#calendar .head {display: flex;width: 100%;margin-top: 10px;justify-content: space-evenly;font-size: 22px;font-weight: 700;color: #50508a90;}#calendar .head .pre-month,#calendar .head .next-month,#calendar .head .pre-month .year,#calendar .head .month {cursor: pointer;}/* 日期部分 */#calendar .main {width: 100%;color: aliceblue;font-size: 20px;font-weight: 900;margin-top: 20px;text-align: center;}#calendar .main table {width: 100%;color: #50508a90;}#calendar .main table tbody tr {width: 100%;}#calendar .main table tbody tr td {height: 36px;line-height: 36px;color: #fff;}.active {background-color: #50508a90;}
日期部分
这个练习案例,最主要的就是对于js
内建对象Date
的使用了
当前日期
首先我们需要拿到当前日期,然后一层一层的拿到以下内容:
- 今天星期几
- 当前月份有多少天
- 这个月的第一天是星期几
获取当前日期是比较简单的
const date = new Date()
const year = date.getFullYear() // 年份
const month = date.getMonth() + 1 // 月份
const weekDay = date.getDay() // 周几
const day = date.getDate() // 日期
后面在多个位置都需要根据日期获取这些数据,所以我把他抽成了一个函数,通过外界传入的日期对象
获取对应的相关数据
function getDate(date) {const year = date.getFullYear() // 年份const month = date.getMonth() + 1 // 月份const weekDay = date.getDay() // 周几const day = date.getDate() // 日期return {year,month,weekDay,day,}
}
注意:
Date
对象的getMonth()
获取到的月数是从零开始的
获取本月的天数
获取当前月数的方法,我想半天没想到,后来查MDN
(还是对原生Date
对象的用法不太熟悉),找到了setDate
方法,该方法根据本地时间来指定一个日期对象的天数,如果当我们传入的天数超出了该月的合理范围,它会根据一定规则进行更新对象:
原时间对象会被改变
- 传入 0 :设置为上一个月的最后一天
- -1 :设置为上一个月的倒数第二天
- 32 :超出了当月的范围,往下一个月类推
根据上面的特点,所以我们可有下面的方法来获取某个月的天数
function getMonthDays(date) {// 将日期设置为32,表示自动计算为下个月的第几天(这取决于当前月份有多少天)let oldDate = new Date()date.setDate(32)let days = 32 - date.getDate()let dayArrs = []let i = 1while (i <= days) {dayArrs.push(oldDate.setDate(i))i++}// 返回当前月份的天数return {days,dayArrs,}
}
在这个方法中,不仅获取到了天数,也将每个日期对应的时间戳返回了
获取第一天的星期数
对于这个功能没有单独抽取方法,大概思路就是,使用setDate
方法,将日期设置为1,然后getDay
// 这里使用 copyDate 是因为 setDate会改变源对象,影响了后面的操作,开始找半天没找到哪里不对
let firstDay = new Date(copyDate.setDate(1)).getDay()
收尾工作
编写一个renderDate
函数用于渲染操作,同时也方便在其他方法中调用(如事件,初始化操作),这里用了表格,所以就根据日期的特点,采用的是6 x 7
的表格,所以里边套了两层循环,在循环中获取了哪一个日期是当前活跃的
function renderDate(date) {const copyDate = new Date(date) // 拷贝一份,防止后面一不小心改了tbody.innerHTML = "" // 清空之前的内容 Tconst { year, month, day } = getDate(date)// 获取当前的年月日const { dayArrs, days } = getCountDays(date)// 获取本月所有的时间戳, 以及本月的天数//#regioncurrentMonth = month // 记录状态currentYear = year // 记录状态//#endregion//#region 头部展示部分yearEl.innerHTML = yearmonthEl.innerHTML = month + "月"//#endregion// 用于统计当前已经渲染上的格子数let count = 0// 本月的第一天的星期数let firstDay = new Date(copyDate.setDate(1)).getDay()// 用于暂存创建的 tr 元素let trs = document.createDocumentFragment()for (let i = 0; i < 6; i++) {// 第一层循环代表行数let tr = document.createElement("tr")// 用于暂存创建的 td 元素let tds = document.createDocumentFragment()for (let j = 0; j < 7; j++) {// 这一层表示列数let td = document.createElement("td")// 当前日期的星期数let day = new Date(dayArrs[count]).getDay()if (i === 0 && j < firstDay) {// 这里的判断用于跳过 1 号之前的日期格子tds.append(td)continue}if (count < days) {// 如果以渲染的格子数小于天数就继续添加if (new Date(dayArrs[count]).getDate() === new Date().getDate()) {// 将当前日期设置为激活状态td.classList.add("active")}td.innerHTML = new Date(dayArrs[count]).getDate()}tds.append(td)count++}tr.append(tds)trs.append(tr)}tbody.append(trs)}
完成该函数之后,我们通过一个IIFE
进行初始化操作
(function () {let date = new Date() // 获取当前日期renderDate(date)})()
结束语
到这里,具有基本功能的日历差不多就实现了,虽然功能比较简单,但是我还是花了好长时间完成,不过也算是对Date
熟悉了些了,这波不亏!后续完成更加复杂的功能
简单的日历组件
前端练手案例之日历(原生)一相关推荐
- 2022最新版40个前端练手项目【附视频+源码】
不管学习哪门语言都希望能做出实际的东西来,这个实际的东西当然就是项目啦, 不用多 说,大家都知道学编程语言一定要做项目才行. 本次给到大家的是40个前端实战练手项目(附源码和视频讲解),希望对大家有一 ...
- 新手前端练手网站_程序员从入门到入狱:必收藏的七大网站
作为一个正在自学JAVA的菜鸡,我把我在学习中用到的网站整理了一下,分享给和我一样正在学习编程的小白们. 1.菜鸟教程 菜鸟教程是零基础小白入门的一个必备网站,菜鸟教程包含了所有跟编程有关的技术.从前 ...
- 新手前端练手网站_影视后期新手大礼包
点击上方蓝色字关注我们~ 为什么很多人学习影视后期学不下去?为什么很多人学习影视后期不知道是为了什么?无论是工作需要,或者兴趣爱好,又或者转行设计.还在迷茫的你,请认真看完下面的视频,会对你有十分大的 ...
- 5个前端练手项目(html css js canvas)
前言: 首先祝大家端午节快乐.本篇文章有5个练手项目 对于刚学完前端三剑客的你们.应该是一个很好的实践 目录
- 新手前端练手网站_编程到底难不难学?新手入门选择哪种语言好?
以下内容适合的读者:想要学习编程的小白 一.编程到底难不难学? 对于这个问题我的回答是不知道,学会了编程的人会说好学,中途就放弃的人会说很难,任何知识想要掌握好都不是一件容易的事情.所以我决定用自己的 ...
- Vue介绍以及练手案例——音乐播放器(搜索音乐、听歌、看评论、看mv等)(持续更新)
Vue概述 它是一种 javascript框架 可以简化DOM操作 进行响应式数据驱动 el: 挂载点 vue实例的作用范围:vue会管理 el 选项所命中的元素及其内部的后代元素. 可以使用其他选择 ...
- 自学web前端练手——js的考试倒计时
考试倒计时,并附带15分钟和5分钟的图片更换.(没调整统一的图片大小) 起初文本一直出不来,搞了半小时(一条一条的检查排查错误),最后把setInterval从函数体中弄出来就好了,吐了_(:з」∠) ...
- 前端练手项目 HTML 游戏叠高塔(包含源码)
叠高塔游戏通过点击[屏幕]或按[空格键]来放置积木. 这个游戏的灵感来源于iPhone上的游戏 Stack: https://itunes.apple.com/us/app/stack/id10804 ...
- web前端练手小项目——仿照小米商城
大部分是静态页面,使用的js知识只有一点点 实现的效果: 实现的html代码: <!DOCTYPE html> <html lang="en"> <h ...
最新文章
- 一个查看全部用户的磁盘空间使用情况的脚本
- 【转】秒杀系统架构分析与实战
- linux闹钟软件下载,电量充满警示闹铃
- RTP/RTCP中的Jitter
- 关于数组表示的二叉结构中,下标乘除法对应关系的理解
- 从代码到300优质客户,用户画像在销售的实战应用
- Thinkphp报错:fields not exists:[status]
- System Exception:故障解决:端口已被占用 1080--->的处理方法
- 我的爷爷(知识渊博的下乡知青)
- 从《三体》中的“降维打击”看网络世界,论维度升级的方法与实践
- 图像表头数据读取,图像数据块读取,图像类型转换
- bootstrap登录模板
- c语言获奖程序,1987年国际C语言混乱代码大赛获奖的一行代码
- bluez——mgmt分析
- 如何为你的网站添加标志性的图标(头像)呢?
- 安全单点登录(SSO)解决方案
- Zoom and pan, introduction to FabricJS part 5(缩放和平移,介绍Fabric.js第五部分)
- 治安防控平台搭建,为您打造平安社区
- 9岁有赞:新零售业务快速增长 推新品牌扶持计划
- 浅析企业私有云中的存储架构