基于Vue开发一个日历组件

最近在做一个类似课程表的需求,需要自制一个日历来支持功能及展现,就顺便研究一下应该怎么开发日历组件。

更新

  • 2.23修复了2026年2月份会渲染多一行的bug,谢谢@深蓝一人童鞋提出的bug,解决方案是给二月份的日历做特殊处理,new Date(year, month 1, 0).getDay() === 6时不会再渲染后面的日期。
  • 下班更新一哈,更科学的逻辑
    // if (total_calendar_list.length > 35) {
    //   nextNum = 42 - total_calendar_list.length;
    // } else {
    //   nextNum = 35 - total_calendar_list.length;
    // }// if (month === 1 && new Date(year, month, 0).getDay() === 6) {
    //   nextNum = 0
    // }nextNum = 6 - new Date(year, month 1, 0).getDay()
    

本文主要涉及以下内容:

  • 怎么开发一套日历皮肤?
  • 怎么计算年月日?
  • 怎么开发日历相关的功能?
  • 总结&DEMO源码

怎么开发一套日历皮肤?

层层分离,块块独立

在梳理日历逻辑之前我想先记录一下日历样式相关的问题:

下面是借鉴px2rem模式,写的基于vw为主单位的自适应转化。简单来说,就是在我们的设计稿是iPhone8一倍图的情况下,计算出某元素宽度与375(iPhone8最大宽度)的比例再与100vw相乘就得到了,该元素的vw值。因为vw是相对于屏幕的百分比单位,所以就能达到我们想要的自适应效果啦,不同的屏幕里,同一元素的展现比例是一致的。

// 借鉴了Rem布局
@function pxWithVw($n) {@return 100vw * $n / 375;
}
// 规定极限宽度,避免PC上观感太差
@function pxWithVwMax($n) {@return 480px * $n / 375;
}

有了上面这段SCSS的函数,我们就基本可以不用考虑屏幕适配的问题了,可以尽情的敲样式啦。关于日历的样式,其实说复杂也还好,我们只需要在做之前好好的分一下层级就好了。

如同上图,每一个框表示一层元素,最后会有这样的布局--

<!--最外层的div限定整个日历的宽度以及一些圆角阴影等样式-->
<div class="calendar"><!--header则为上图中绿色框的内容,包含上下月切换以及日历title--><div class="calendar__header"></div><!--顾名思义main则是整个日历的核心内容,也就是日期的展示区域--><div class="calendar__main"><!--星期一~星期日的展示头,列表渲染固定的7个block--><div class="main__block-head"></div><!--相应月份的日期展示区域,列表渲染--><div class="main__block"></div></div>
</div>

也许大家看完之后比较奇怪calendar__main里面的布局,为什么没有把固定的展示头分离开来,当你实际写到这里的时候会发现其实没有这个必要。

因为我们用了pxWithVw去规定calendar__main的宽度以及每个block的宽度,也就确保了每7块元素必定会占满我们一行,再利用justify-content: space-around确保我们每块元素的间隙一致即可。

好了,层层分离说完了,什么是块块独立呢?

主要指的是日期的展示块,我们是每块独立的,这样在我们渲染的时候可以很方便的决定应该以什么样式去展示他,或是应该给他绑定怎么样的事件,给我们精密控制每个日期的展示提供了便利。

怎么计算年月日?

本小节的内容总结起来其实就一句话--

我们只需要知道,某个月的1号是星期几,就能把整个日历渲染出来

关于年月日的计算,我这边有两种模式,一种是只计算当月日期,另一种则是将整年的日期都计算出来。在本篇文章里我想着重记录第一种写法,大家想了解第二种的话可以到我的github里看看这个日历的demo。

我们先来个看图说话,这个二月份有28天,1号是星期四。那是不是说,我们只要从周四开始,按顺序渲染出28个'main__block'就好了呢?其实就是这样,关键是怎么把我们的1号定位到周四,只要这个能够准确定位到,我们的日历自然就出来了。

// 定义每个月的天数,如果是闰年第二月改为29天
// year=2018;month=1(js--month=0~11)
let daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {daysInMonth[1] = 29;
}
// 获得指定年月的1号是星期几
let targetDay = new Date(year, month, 1).getDay();
// 将要在calendar__main中渲染的列表
let total_calendar_list = [];
let preNum = targetDay;
// 首先先说一下,我们的日期是(日--六)这个顺序也就是(0--6)
// 有了上述的前提我们可以认为targetDay为多少,我们就只需要在total_calendar_list的数组中push几个content为''的obj作为占位
if (targetDay > 0) {for (let i = 0; i < preNum; i  ) {let obj = {type: "pre",content: ""};total_calendar_list.push(obj);}
}

这样一来,1号的位置自然而然就到了我们需要的星期四了,接下来就只需要按顺序渲染就ok啦。下面是剩下日期数组填充,填充完毕之后return出来供我们view层使用。

for (let i = 0; i < daysInMonth[month]; i  ) {let obj = {type: "normal",content: i   1};total_calendar_list.push(obj);
}
nextNum = 6 - new Date(year, month 1, 0).getDay()
// 与上面的type=pre同理
for (let i = 0; i < nextNum; i  ) {let obj = {type: "next",content: ""};total_calendar_list.push(obj);
}
return total_calendar_list;

怎么开发日历相关的功能?

如何选择上一个月或下一个月?

data() {return {// ...selectedYear: new Date().getFullYear(),selectedMonth: new Date().getMonth(),selectedDate: new Date().getDate()};
}handlePreMonth() {if (this.selectedMonth === 0) {this.selectedYear = this.selectedYear - 1this.selectedMonth = 11this.selectedDate = 1} else {this.selectedMonth = this.selectedMonth - 1this.selectedDate = 1}
}handleNextMonth() {if (this.selectedMonth === 11) {this.selectedYear = this.selectedYear   1this.selectedMonth = 0this.selectedDate = 1} else {this.selectedMonth = this.selectedMonth   1this.selectedDate = 1}
}

就是这么简单,需要注意的点是跨年的时间转换,我们需要在变更月份的同时把年份也改变,这样才能渲染出正确的日期。

也许大家会有疑问,怎么变更了月份或年份之后不需要重新计算一次日期呢?其实是有计算的,不知大家是否还记得,vue可是数据驱动变更的,我们只需要关注数据的变更即可,其他东西vue都会帮我们解决。

如果选中某一天?

handleDayClick(item) {if (item.type === 'normal') {// do anything...this.selectedDate = Number(item.content)}
}

在渲染列表的时候我就给每一个block绑定了click事件,这样做的好处就是调用十分方便,点击每一个block的时候,可以获取该block的内容然后do anything you like

当然我们也可以给外层的父级元素绑定事件监听,通过事件流来解决每个block的点击事件,这里看个人习惯~毕竟元素数量不是特别多

总结

一个移动端日历貌似也有惊无险的完成啦,总体来说日历这活还是偏样式方面的,对逻辑的要求不是特别高,对样式的要求倒是挺高的需要对flexbox布局有一定理解,才能迅速的吧日历的骨架搭起来,虽然也不一定说必须用flex,不过个人认为用flex的效率会稍高一些。

基于Vue写的日历DEMO--Github

啰嗦一下,为什么想起来写日历?当然是业务需求啦,所以说这个日历组件一开始是react写的,后面想在vue里也尝试一下就改成了vue。其实在react里面写也是大同小异啦,只不过我会把日期的block抽离成无状态组件,也不为啥就感觉比较好看:)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 打开word乱码怎么办,如何解决php word 乱码问题

php word乱码的解决办法&#xff1a;首先打开“/Writer/Word2007/Base.php”文件&#xff1b;然后添加“$objWriter->writeAttribute(‘w:eastAsia’, $font)”内容&#xff1b;最后保存修改即可。PHPword解决中文乱码一、增加东亚字体支持打开并编辑路径/Writer/Word2007/B…

Java开发人员访谈的MindMap

多年来&#xff0c;我曾在许多Java开发人员访谈中担任小组成员。 之前&#xff0c;我曾写过一篇标题为“成功进行软件工程师技术面试的7大技巧”的文章&#xff0c;其中涵盖了很少的一般准则。 在本文中&#xff0c;我将分享一个思维导图&#xff0c;其中包含Java开发人员访谈中…

送给大家一个好看的简历神器

很多人看到里边有好看的东西就习惯性的点进来看看&#xff0c;还一边点一边想 —— 好看的简历我见多了&#xff0c;你这个又能好看到哪里去。我想差不多可以&#xff1a; 哪里吧因为最近有在准备简历&#xff0c;就习惯性的找一找有没有现成的简历模板。结果全是付费的&#x…

PHP简单实现单点登录功能示例

1.准备两个虚拟域名 127.0.0.1 www.openpoor.com127.0.0.1 www.myspace.com 2.在openpoor的根目录下创建以下文件 index.PHP 123456789101112131415161718<?phpsession_start();?><!DOCTYPE html><html><head><meta charset"UTF-8"/&…

JUNG 计算图属性,中心度,偏心率,直径,半径

本文介绍利用Java的第三方API JUNG 计算图中&#xff1a; closeness centrality&#xff1b;// 图中某节点的 接近中心性/亲密中心性 betweenness centrality&#xff1b;// 图中某节点的 中介中心性/介数中心性 distance; // 图中两节点的最短距离 eccentricity; // 图中某节…

Java VM –提防YoungGen空间

您可能从我们以前的面向性能的文章中看到&#xff0c;健康的JVM是实现最佳应用程序性能和稳定性的最重要目标之一。 这样的健康评估通常仅关注主要收集的频率&#xff08;避免&#xff09;或检测内存泄漏的存在。 年轻一代空间或短寿命物体的大小和足迹如何&#xff1f; 本文…

小程序绘图工具painter-json文件绘制保存分享图-可点击任意元素触发函数

Painter是由酷家乐移动前端团队打造的一款小程序绘图组件。 原项目地址&#xff1a;https://github.com/Kujiale-Mobile/Painter 新版地址&#xff1a;https://github.com/shesw/Painter 这款交互版原来是为了针对业务中的新需求而由我自己开发的&#xff0c;后来需求改动&a…

4 张动图解释为什么(什么时候)使用 Redux

dev-reading/fe 是一个阅读、导读、速读的 repo&#xff0c;不要依赖于 dev-reading/fe 学习知识。本 repo 只是一个快速了解文章内容的工具&#xff0c;并不提供全文解读和翻译。你可以通过本平台快速了解文章里面的内容&#xff0c;找到感兴趣的文章&#xff0c;然后去阅读全…

您正在使用什么垃圾收集器?

我们的研究实验室正全速前进。 随着最近的资金注入 &#xff0c;我们只能保证我们不断创新的步伐只会加快。 我们进行的部分研究与GC优化有关。 在处理这个有趣领域中的问题时&#xff0c;我们认为可以分享一些有关GC算法使用的见解。 为此&#xff0c;我们对使用特定GC算法的…

前端布局推进剂 - 间距规范化

我是一个爱折腾设计的前端&#xff0c;一直都在标榜自己的页面还原是多么的牛 X 。怎么做到页面还原&#xff1f;我有一个最笨但是有效的方法&#xff0c;就是把设计稿直接存成图片&#xff0c;作为背景图然后临摹着设计稿进行开发。我觉得自己太有才了。像素级还原有没有&…

echarts折线图相关

optionJKDLine {  title: {text: 告警数量趋势图,textStyle:{  //标题样式fontStyle:normal,fontFamily:sans-serif,fontSize:12    }},tooltip: {trigger: axis},legend: {  //图例,默认显示},grid: {  //图表距离left: -3%,right: 5%,bottom: 3%,top:20%,contai…

一个关于fixed抖动的小bug

前言 大家都知道position: fixed用于生成绝对定位的元素&#xff0c;相对于浏览器窗口进行定位。 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 突然发现自己之前写的网页有个小bug&#xff1a;在购买页面的…

腾讯Node.js基础设施TSW正式开源

经过六年的迭代与沉淀&#xff0c;腾讯Tencent Server Web (以下简称TSW)这一公司级运维组件于今日正式开源。TSW是面向WEB前端开发者&#xff0c;以提升问题定位效率为初衷&#xff0c;提供云抓包、全息日志和异常发现的Node.js基础设施。TSW每天为百亿次请求提供稳定服务&…

ORM框架greenDao 2 (用于了解旧版本的使用方法,目前最新版本为3.2.2,使用注释的方式来生成)...

摘要&#xff1a; Android中对SQLite数据库使用&#xff0c;是一件非常频繁的事情。现今&#xff0c;也有非常多的SQLite处理的开源框架&#xff0c;其中最著名的greenDao&#xff0c;它以占用资源少&#xff0c;处理效率高等特点&#xff0c;成为优秀的ORM框架之一。那么对于g…

配置MySQL以进行ADF开发

大家好。 今天&#xff0c;我将向您展示如何为Oracle ADF开发配置MySQL数据库。 恕我直言&#xff0c;当您将ADF与其他数据库而不是Oracle DB一起使用时&#xff0c;您将无法使用Oracle ADF的全部功能&#xff0c;有时您会发现自己正在寻找解决方法&#xff0c;以实现某些行为…

React Native面试知识点

本文原创首发于公众号&#xff1a;ReactNative开发圈&#xff0c;转载需注明出处。 本文会不定期不断更新&#xff0c;想查看最新版本请移步至https://github.com/forrest23/react-native-interview 1.React Native相对于原生的ios和Android有哪些优势&#xff1f; 1.性能媲美…

KIE-WB / JBPM控制台Ng –配置

大家好&#xff0c;这是我上一篇文章中有关如何使用jBPM Console的后续文章 。 这篇文章的主要思想是描述为了在您自己的公司中使用它&#xff0c;您需要对jBPM Console NG进行一些最常见的配置。 但是在讨论技术细节之前&#xff0c;我们将介绍KIE Workbench&#xff08;KIE-W…

自己写一个H5项目CI系统

持续集成&#xff08;Continuous integration&#xff0c;简称CI)系统在软件自动化构建&#xff08;包括编译、发布、自动化测试&#xff09;方面有着重要的作用&#xff0c;在之前&#xff0c;前端项目简单&#xff0c;很多时候发布都只是一些简单的拷贝&#xff0c;而随着web…

25.QT-模型视图

模型视图设计模式的核心思想 使模型(数据)与视图(显示)相分离模型只需要对外提供标准接口存取数据,无需数据如何显示视图只需要自定义数据的显示方式,无需数据如何组织存储当数据发生改变时,会通过信号通知视图当用户与视图进行交互时,会通过信号向模型发送交互信息 在QT中提供…

休眠事实:多级访存

在多个级别上检索根实体及其子关联是很常见的。 在我们的示例中&#xff0c;我们需要加载一个包含其树&#xff0c;分支和叶子的森林&#xff0c;并且我们将尝试查看Hibernate对于三种集合类型的行为&#xff1a;集合&#xff0c;索引列表和包。 这是我们的类层次结构的样子&…