日历前端📅渲染开发记录

需求分析

突然接到一个排班的需求。

看了下算是比较老的项目,使用的是vue2+element开发的,使用的是element的UI组件库。去查看下element的Calendar组件。⬇️长这样

看起来没什么大问题。星期几信息和每天的信息都很详细。但是和我的需求不符合,排班需要在一个日期范围内显示一些内容。显然element的calendar文档只能选中单个日期,无法完全满足我的需求。

手滑不小心点到了电脑的日历📅组件⬇️

于是就想着按照Apple 的日历应用UI来做。

代码逻辑分析

  • 使用table还是flex布局来渲染?
  • 当当前月份的第一天不是周日怎么办?
  • 当当前月份的最后一天不是周六怎么办?

代码实现

选择table来布局。根据table的布局来定数据结构

css 复制代码
 table
  thead
   th
  tbody
   tr
    td

优先渲染表头

由于项目内部已经安装了moment时间处理库,所以本文都使用moment时间处理库来做时间处理。当然你也可以用类似的dayjs来处理一样的。主要使用的是moment时间的加减方法,用到的方法如下。

  • fn.startOf
  • fn.endOf
  • fn.add
  • fn.subtract
  • fn.format
  • fn.day()

实现代码思路

  • 通过fn.startOffn.endOf来获取需要截取的开始结束时间区间。
  • 判断上一步的开始时间是星期几,结束时间是星期几。如果开始时间不是星期天或者最后一天不是星期六则需要补全上个月的日期和下个月的日期。因为我们是以7天为一个横向区间。

代码实现

日历头的数据渲染

css 复制代码
 const titles = {
     0: '周日',
     1: '周一',
     2: '周二',
     3: '周三',
     4: '周四',
     5: '周五',
     6: '周六',
 };
 let i = 0;
 while (i < 7) {
     this.calendarHeader.push({
         title: titles[i],
         value: i,
     });
     i++;
 }

显示区间的数据渲染

kotlin 复制代码
 const startDate = this.$moment(this.currentDate).startOf('month');
 const endDate = this.$moment(this.currentDate).endOf('month');
 let monthdays = [];
 for (let i = startDate; i <= endDate; i.add(1, 'day')) {
     monthdays.push({
         date: i,
         week: this.$moment(i).day(),
         format: i.format('YYYY/MM/DD'),
         day: i.format('DD'),
         data: {}
     });
 }

判断是否需要填充上个月的日期作为本月补充显示

ini 复制代码
 const startDay = monthdays[0];
 if (startDay.week !== 0) {
     // 填补上月在本周的日期
     const {format, week} = startDay;
     let frontDays = [];
     for (let i= week -1; i >= 0;i--) {
         const date = this.$moment(format).subtract( i, 'day');
         const subtractDay = this.$moment(format).subtract( i + 1, 'day');
         const day = {
             date,
             week: subtractDay.day(),
             format:  subtractDay.format('YYYY/MM/DD'),
             day: subtractDay.format('DD'),
             data: {
                 disabled: true
             }
         }
         frontDays.push(day);
     }
     monthdays = [...frontDays, ...monthdays]
 }

判断是否需要填充下个月的日期作为本月补充显示

css 复制代码
 const endDay = monthdays[monthdays.length - 1]
 if(endDay.week !== 6) {
     const {format, week} = endDay;
     let j = 1;
     for (let i = week;i < 6;i++) {
         monthdays.push({
             date: this.$moment(format).add( j, 'day'),
             week: week + j,
             format:  this.$moment(format).add( j, 'day').format('YYYY/MM/DD'),
             day: this.$moment(format).add( j, 'day').format('DD'),
             data: {
                 disabled: true
             }
         });
         j++
     }
 }

以0-6为区间判断一周做数据切割

ini 复制代码
 let _week = [];
 for (let i = 0; i < monthdays.length; i++) {
     const { week } = monthdays[i];
     if (week <= 6 && week !== 0) {
         _week.push(monthdays[i]);
         if (i === monthdays.length - 1) {
             // 如果这个月的最后几天没有星期天就把剩下的天数单独分为一周
             this.calendar.push(_week);
             _week = [];
         }
     } else if (week == 0) {
         this.calendar.push(_week);
         // 如果是周日则换一行
         _week = [];
         _week.push(monthdays[i]);
     }
 }

至此完成之后页面长这样

相关推荐
蒟蒻星球住民3 分钟前
web应用技术作业01
前端·javascript·firefox
Csvn10 分钟前
前端团队协作
前端
道友可好23 分钟前
Superpowers:给 AI 编程助手装上超能力
前端·人工智能·后端
协享科技24 分钟前
Vue 3 实现抖音式卡片滑动交互:从零到完整方案
前端·vue.js·交互·ai编程·英语·自考英语
_xaboy35 分钟前
开源Vue组件FormCreate通过 JSON 生成TinyVue表单
前端·vue.js·低代码·开源·json·表单设计器
ZC跨境爬虫40 分钟前
跟着 MDN 学CSS day_44:响应式设计——让网页适配所有屏幕的完整指南
前端·css·ui·html·tensorflow
前端不太难1 小时前
Edge AI 时代:从数据中心到终端,算力如何无处不在?
前端·人工智能·edge
Highcharts.js1 小时前
Highcharts v13 全新时间轴标签边界格式|让时间维度表达更智能
前端·信息可视化·时间序列·图表开发·chart·自定义标签·可视化开发
lichenyang4531 小时前
鸿蒙研读 10:@Provider/@Consumer、RelativeContainer、onNewWant
前端
大湿兄啊啊啊1 小时前
MID360S调试
java·服务器·前端