日历前端📅渲染开发记录

需求分析

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

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

至此完成之后页面长这样

相关推荐
2501_9209317040 分钟前
React Native鸿蒙跨平台实现推箱子游戏,完成玩家移动与箱子推动,当所有箱子都被推到目标位置时,玩家获胜
javascript·react native·react.js·游戏·ecmascript·harmonyos
layman05281 小时前
webpack5 css-loader:从基础到原理
前端·css·webpack
半桔1 小时前
【前端小站】CSS 样式美学:从基础语法到界面精筑的实战宝典
前端·css·html
AI老李1 小时前
PostCSS完全指南:功能/配置/插件/SourceMap/AST/插件开发/自定义语法
前端·javascript·postcss
_OP_CHEN1 小时前
【前端开发之CSS】(一)初识 CSS:网页化妆术的终极指南,新手也能轻松拿捏页面美化!
前端·css·html·网页开发·样式表·界面美化
啊哈一半醒1 小时前
CSS 主流布局
前端·css·css布局·标准流 浮动 定位·flex grid 响应式布局
PHP武器库1 小时前
ULUI:不止于按钮和菜单,一个专注于“业务组件”的纯 CSS 框架
前端·css
方也_arkling1 小时前
Element Plus主题色定制
javascript·sass
电商API_180079052471 小时前
第三方淘宝商品详情 API 全维度调用指南:从技术对接到生产落地
java·大数据·前端·数据库·人工智能·网络爬虫
晓晓莺歌1 小时前
vue3某一个路由切换,导致所有路由页面均变成空白页
前端·vue.js