广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue实现万年日历的示例详解
  • 241
分享到

Vue实现万年日历的示例详解

Vue实现万年日历Vue万年日历Vue万年历 2023-01-12 09:01:23 241人浏览 独家记忆
摘要

目录前言1.日历的布局2.日期数据的产生3.年月的变化4.连续最长打卡日期5.补卡日期前言 又是一个老生常谈的功能,接下来会从零实现一个万年日历,从布局到逻辑,再到随处可见的打卡功能

前言

又是一个老生常谈的功能,接下来会从零实现一个万年日历,从布局到逻辑,再到随处可见的打卡功能。涉及的内容有:

  • 日历的布局
  • 日期数据的产生
  • 年月的变化
  • 连续最长打卡日期
  • 补卡逻辑

1.日历的布局

<template>
  <div class="calendar">
    <!-- 年份和日期变化 -->
    <div class="select">
      <span class="select-icon select-sub" @click="changeYear(-1)">《</span>
      <span class="select-icon select-sub select-month" @click="changeMonth(-1)"><</span>
      <span>{{ currentMonth }}</span>
      <span class="select-icon select-add select-month" @click="changeMonth(+1)">></span>
      <span class="select-icon select-add" @click="changeYear(+1)">》</span>
    </div>
    <!-- 日历标题 -->
    <ul class="calendar-header">
      <li v-for="(item, index) in headerData" :key="index" class="calendar-header-item">
        <span>{{ item }}</span>
      </li>
    </ul>
    <!-- 日期内容 -->
    <div class="calendar-box">
      <div class="calendar-box-item" :class="{ delMark: !hasRemarkDays.includes(item) }" v-for="(item, index) in baseDateList" :key="index">
        <!-- 最高层级显示圆形日期 -->
        <div class="item-wrap" :class="{ hasMarked: hasRemarkDays.includes(item) }" @click="toRemark(item, currentDate)">
          <span class="item-date">{{ item ? item : "" }}</span>
          <span class="item-patch" v-if="isshowPatch && !hasRemarkDays.includes(item) && item && item < currentDate">补卡</span>
          <span class="item-current" v-if="currentDate == item"><i></i></span>
          <span class="item-continue" v-if="continueMarkObj.maxDay == item">连续{{ continueMarkObj.maxLen }}天</span>
        </div>
        <!-- 全遮罩背景淡橙色背景 -->
        <span class="all-mark" v-if="hasRemarkDays.includes(item)"></span>
        <!-- 左右遮罩,如果左边无打卡,遮住;如果右边无打卡,遮住 -->
        <span class="left-mark" v-if="index % 7 === 0 || !hasRemarkDays.includes(item - 1)"></span>
        <span class="right-mark" v-if="index % 7 === 6 || !hasRemarkDays.includes(item + 1)"></span>
      </div>
    </div>
  </div>
</template>

2.日期数据的产生

  computed: {
    // 返回当前的实际天数,从周一算起
    baseDateList() {
      let date = new Date(this.currentMonth);
      let monthFlag = date.getMonth() + 1;
      let yearFlag = date.getFullYear();
      let currentData = date.getDay();
      let dayLength = new Date(yearFlag, monthFlag, 0).getDate();

      // 周一之前的补0
      let dateBaseData = [];
      for (let i = 0; i < currentData; i++) {
        dateBaseData.push(0);
      }
      // 周一之后的实际填写
      for (let i = 0; i < dayLength; i++) {
        dateBaseData.push(i + 1);
      }

      return dateBaseData;
    },
  }

其中currentData表示今天是周几,在此之前的数组都补充为0,dayLength表示这月共多少天,然后,全部push进日期数据中。通过flex布局中的flex-wrap: wrap;让其自动换行即可。

3.年月的变化

// 修改年:当type = +1时,表示加一年,为-1时反之
changeYear(type) {
  let time = new Date(this.currentMonth);
  let year = time.getFullYear() + type;
  let month = time.getMonth() + 1;
  this.currentMonth = `${year}-${month}`;
},
// 修改月:当type = -1时,表示加一月,为-1时次之
changeMonth(type) {
  let time = new Date(this.currentMonth);
  let year = time.getFullYear();
  let month = time.getMonth() + 1;
  if (month === 12 && type > 0) { // 12月,并且是加的情况,年加1,月变为1
    year++
    month = 1
  } else if(month === 1 && type < 0) { // 1月,并且是减的情况,年减1,月变为12
    year--
    month = 12
  } else { // 其他情况,直接变化变量type的大小
    month += type
  }
  this.currentMonth = `${year}-${month}`;
},

引入type,既是加减的标志位,又是变量的大小。

4.连续最长打卡日期

getMaxDay() {
  let arr = this.hasRemarkDays;
  let buffChild = [];
  let max = [];
  
  for (let i = 0; i < arr.length; i++) {
    // 如果子集不连续了,重新进行赋值和更新
    if (buffChild.length && arr[i] - buffChild[buffChild.length - 1] > 1) {
      max = max.length > buffChild.length ? [...max] : [...buffChild];
      buffChild = [];
      buffChild.push(arr[i]);
      continue;
    }
    // 如果不是,直接进行累计
    buffChild.push(arr[i]);
  }
  return max.length > buffChild.length ? [...max] : [...buffChild];
},

假设max是最大的数组,那么,每次找到连续的数组都max进行对比并更新。在节点中,通过:class="{ hasMarked: hasRemarkDays.includes(item) }"的方式,为其添加hasMarked的样式。

5.补卡日期

补卡逻辑很简单,当前日期之前的日期,均可进行补卡,然后,在触发的方法中,通过$emit的方式向父组件传递需要补卡的日期,并触发补卡逻辑。

总结:日历的实现主要是应用javascript中Date对象的api和经典的flex布局,而最长连续打卡是常规算法最长连续子序列的实现方式之一。

到此这篇关于Vue实现万年日历的示例详解的文章就介绍到这了,更多相关Vue万年日历内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Vue实现万年日历的示例详解

本文链接: https://www.lsjlt.com/news/177454.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作