日历前端📅渲染开发记录

需求分析

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

看了下算是比较老的项目,使用的是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]);
     }
 }

至此完成之后页面长这样

相关推荐
iDao技术魔方2 小时前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
javascript·vue.js·ecmascript
历程里程碑2 小时前
普通数组-----除了自身以外数组的乘积
大数据·javascript·python·算法·elasticsearch·搜索引擎·flask
摸鱼的春哥2 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响2 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
Amumu121382 小时前
Vue3 Composition API(一)
开发语言·javascript·ecmascript
C澒2 小时前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅2 小时前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘2 小时前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
hzb666662 小时前
unictf2026
开发语言·javascript·安全·web安全·php
恋猫de小郭4 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter