js实现日历 完整版

news2025/6/8 10:42:56
<template>
  <div id="calendar">
    <!-- 年份 月份 -->
    <div class="title">
      <div class="label">活动日历</div>
      <div class="total">当前活动 {{ list.length }}</div>
    </div>
    <div class="content">
      <ul class="month">
        <!--点击会触发pickpre函数,重新刷新当前日期 @click(vue v-on:click缩写) -->
        <li class="arrow">
          <span
            @click="pickPre(currentYear, currentMonth, 'year')"
            style="margin-right: 20px"
            >❮❮</span
          >
          <span @click="pickPre(currentYear, currentMonth, 'month')"></span>
        </li>
        <li class="year-month">
          <span class="choose-year">{{ currentYear }}</span>
          <span class="choose-month">{{ currentMonth }}</span>
        </li>
        <li class="arrow">
          <span @click="pickNext(currentYear, currentMonth, 'month')"></span>
          <span
            @click="pickNext(currentYear, currentMonth, 'year')"
            style="margin-left: 20px"
            >❯❯</span
          >
        </li>
      </ul>
      <!-- 星期 -->
      <ul class="weekdays">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      <!-- 日期 -->
      <ul class="days">
        <!-- 核心 v-for循环 每一次循环用<li>标签创建一天 -->
        <li v-for="(item, index) in days" :key="index">
          <!--本月-->
          <!--如果不是本月  改变类名加灰色-->

          <span
            v-if="item.month != currentMonth"
            class="other-month"
            @click="clickOtherItem(item)"
            >{{ +item.date }}</span
          >

          <!--如果是本月  还需要判断是不是这一天-->
          <span v-else>
            <!--今天  同年同月同日-->
            <span
              class="current-month"
              @click="clickItem(item)"
              :class="{
                'current-day':
                  item.day.getFullYear() == new Date().getFullYear() &&
                  item.day.getMonth() == new Date().getMonth() &&
                  item.day.getDate() == new Date().getDate(),
                active: item.value === activeTime,
                'not-allow': !item.hasActivity,
                'has-activity': item.hasActivity,
              }"
              >{{ +item.date }}</span
            >
          </span>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name: "",
  components: {},
  mixins: [],
  props: {},
  computed: {},
  watch: {},
  data() {
    return {
      currentDay: 1,
      currentMonth: 1,
      currentYear: 1970,
      currentWeek: 1,
      days: [],
      activeTime: "2023-09-21",
      list: ["2023-09-20", "2023-09-21", "2023-09-11"],
    };
  },
  created() {
    this.initData(null);
  },
  mounted() {},
  methods: {
    // 点击其他月份的 判断
    clickOtherItem(item) {
      if (item.month < this.currentMonth) {
        this.pickPre(this.currentYear, this.currentMonth, "month");
      } else {
        this.pickNext(this.currentYear, this.currentMonth, "month");
      }
    },
    clickItem(item) {
      if (!item.hasActivity) return;
      this.activeTime = item.value;
    },
    initData: function (cur) {
      var date;
      console.log(cur);
      if (cur) {
        date = new Date(cur);
      } else {
        var now = new Date();
        var d = new Date(this.formatDate(now.getFullYear(), now.getMonth(), 1));
        d.setDate(35);
        date = new Date(this.formatDate(d.getFullYear(), d.getMonth() + 1, 1));
      }
      this.currentDay = date.getDate();
      this.currentYear = date.getFullYear();
      this.currentMonth = date.getMonth() + 1;

      this.currentWeek = date.getDay(); // 1...6,0
      if (this.currentWeek == 0) {
        this.currentWeek = 7;
      }
      var str = this.formatDate(
        this.currentYear,
        this.currentMonth,
        this.currentDay
      );
      this.days.length = 0;
      // 今天是周日,放在第一行第7个位置,前面6个
      //初始化本周
      console.log(this.currentWeek, "this.currentWeek");
      for (let i = this.currentWeek - 1; i >= 0; i--) {
        const d = new Date(str);
        d.setDate(d.getDate() - i);
        const day = d;
        const year = d.getFullYear();
        const month =
          d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1;
        const date = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate();
        const value = `${year}-${month}-${date}`;
        const dayobject = {
          year,
          month,
          date,
          value,
          day,
        };
        this.days.push(dayobject); // 将日期放入data 中的days数组 供页面渲染使用
      }
      //其他周
      for (var i = 1; i <= 35 - this.currentWeek; i++) {
        var d = new Date(str);
        d.setDate(d.getDate() + i);
        const day = d;
        const year = d.getFullYear();
        const month =
          d.getMonth() + 1 < 10 ? "0" + (d.getMonth() + 1) : d.getMonth() + 1;
        const date = d.getDate() < 10 ? "0" + d.getDate() : d.getDate();
        const value = year + "-" + month + "-" + date;
        var dayobject = {
          year,
          month,
          date,
          value,
          day,
          hasActivity: false, // 是否有活动数据
        };
        this.days.push(dayobject);
      }
      // 拿到日历数组后 根据返回的有活动的列表进行过滤
      this.days = this.days.map((item) => {
        if (this.list.indexOf(item.value) !== -1) {
          this.$set(item, "hasActivity", true);
        }
        return item;
      });
    },
    pickPre: function (year, month, type) {
      if (type === "month") {
        const preMonth = month - 1 <= 0 ? 12 : month - 1;
        const preYear = month - 1 <= 0 ? year - 1 : year;
        this.initData(this.formatDate(preYear, preMonth, 1));
      } else {
        this.initData(this.formatDate(year - 1, month, 1));
      }
    },
    pickNext: function (year, month, type) {
      if (type === "month") {
        const nextMonth = month + 1 > 12 ? 1 : month + 1;
        const nextYear = month + 1 > 12 ? year + 1 : year;
        this.initData(this.formatDate(nextYear, nextMonth, 1));
      } else {
        this.initData(this.formatDate(year + 1, month, 1));
      }
    },

    // 返回 类似 2016-01-02 格式的字符串
    formatDate: function (year, month, day) {
      var y = year;
      var m = month;
      if (m < 10) m = "0" + m;
      var d = day;
      if (d < 10) d = "0" + d;
      return y + "-" + m + "-" + d;
    },
  },
};
</script>
<style lang="less" scoped>
* {
  box-sizing: border-box;
}
ul,
li {
  list-style: none;
  margin: 0;
  padding: 0;
}
body {
  font-family: Verdana, sans-serif;
  background: #e8f0f3;
}
#calendar {
  width: 440px;
  height: 400px;
  display: flex;
  flex-direction: column;
  padding: 20px;
  margin: 0 auto;
  box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.1),
    0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.title {
  height: 28px;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  .label {
    color: #000;
    font-family: PingFang SC;
    font-size: 16px;
    font-style: normal;
    font-weight: 600;
  }
  .total {
    height: 28px;
    padding: 8px 15px;
    border-radius: 32px;
    background: rgba(0, 91, 255, 0.1);
    display: flex;
    align-items: center;
    color: #005bff;
    font-family: PingFang SC;
    font-size: 14px;
    font-style: normal;
    font-weight: 400;
  }
}
.content {
  display: flex;
  flex: 1;
  height: 0;
  flex-direction: column;
  .month {
    height: 40.25px;
    display: flex;
    justify-content: space-between;
    padding: 0 10px;
    align-items: center;
    .year-month {
      color: rgba(0, 0, 0, 0.85);
      text-align: center;
      font-family: PingFang SC;
      font-size: 16px;
      font-style: normal;
      font-weight: 600;
      .choose-year {
        margin-right: 12px;
      }
    }
    .arrow {
      span:hover {
        cursor: pointer;
        color: #005bff;
      }
    }
  }
  .weekdays {
    height: 40.25px;
    display: flex;
    li {
      cursor: default;
      display: flex;
      align-items: center;
      justify-content: center;
      width: calc(100% / 7);
      height: 40px;
      color: rgba(0, 0, 0, 0.85);
      text-align: center;
      font-family: PingFang SC;
      font-size: 14px;
      font-style: normal;
      font-weight: 400;
    }
  }
  .days {
    flex: 1;
    height: 0;
    display: flex;
    flex-wrap: wrap;
    li {
      display: flex;
      align-items: center;
      justify-content: center;
      width: calc(100% / 7);
      height: 40px;
      color: rgba(0, 0, 0, 0.85);
      text-align: center;
      font-family: PingFang SC;
      font-size: 14px;
      font-style: normal;
      font-weight: 400;
      span {
        width: 34px;
        height: 34px;
        line-height: 34px;
      }
      .has-activity {
        display: inline-block;
        width: 34px;
        height: 34px;
        position: relative;
      }
      .current-day {
        color: #005bff;
      }
      .active {
        color: #fff;
        display: inline-block;
        width: 34px;
        height: 34px;
        background: #005bff;
        border-radius: 50%;
        position: relative;
      }
      .other-month {
        color: rgba(0, 0, 0, 0.45);
        cursor: default;
      }
      .current-month:hover {
        width: 34px;
        height: 34px;
        display: inline-block;
        cursor: pointer;
        background: #f2f2f2;
        color: rgba(0, 0, 0, 0.85);
        border-radius: 50%;
      }
      .active:hover {
        cursor: pointer;
        color: #fff;
        display: inline-block;
        width: 34px;
        height: 34px;
        background: #005bff;
        border-radius: 50%;
      }
      .not-allow:hover {
        cursor: not-allowed;
        background-color: white;
      }
      .has-activity::after {
        content: "";
        position: absolute;
        width: 4px;
        height: 4px;
        border-radius: 50%;
        background-color: #005bff;
        left: 50%;
        bottom: 2px;
        margin-left: -2px;
      }
      .active::after {
        content: "";
        position: absolute;
        width: 4px;
        height: 4px;
        border-radius: 50%;
        background-color: white;
        left: 50%;
        bottom: 2px;
        margin-left: -2px;
      }
    }
  }
}
</style>

在这里插入图片描述

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

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

相关文章

云化XR和沉浸式全息交互技术的探索与思考

// 编者按&#xff1a;计算机图形与仿真技术的发展为人类带来了众多的沉浸式技术。虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;、混合现实&#xff08;MR&#xff09;等技术通过不同程度数字信息与现实环境的融合&#xff0c;为用户带来了全新体…

clickhouse数据库简介,列式存储

clickhouse数据库简介 1、关于列存储 所说的行式存储和列式存储&#xff0c;指的是底层的存储形式&#xff0c;数据在磁盘上的真实存储&#xff0c;至于暴漏在上层的用户的使用是没有区别的&#xff0c;看到的都是一行一行的表格。 idnameuser_id1闪光10266032轨道物流10265…

【计算机毕设选题推荐】幼儿园管理系统SpringBoot+SSM+Vue

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 项目名 基于SpringBoot的幼儿园管理系统 技术栈 SpringBootSSMVueMySQLMaven 文章目录 一、幼儿园管…

记录一个@Transaction注解引发的bug

记录一个Transactional(readOnly true)注解引发的bug 一、问题代码和报错 1-1 问题代码模拟 引发这个问题的三大要素分别是&#xff1a; 事务注解任意数据库操作数据库操作后执行耗时业务&#xff08;耗时超过数据库配置的超时时间&#xff09; //1.这里是问题的核心之一…

基于springboot实现实验室管理系统项目【项目源码+论文说明】

摘要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&#xff0c;成本低等优点。 因此&#xff0c;构建符合…

淘宝商品销量数据接口,淘宝API接口

淘宝商品销量数据接口是淘宝开放平台提供的一种API接口&#xff0c;通过该接口&#xff0c;商家可以获取到淘宝平台上的商品销量数据。 淘宝商品销量数据接口可以用于获取特定商品的销量数据、特定店铺的销量数据、特定类目的销量数据等。商家可以根据自己的需求来调用该接口&…

python基础教程:print()函数知识点总结

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 print() 方法用于打印输出 语法&#xff1a; print(*objects, sep , end\n, filesys.stdout, flushFalse)参数 objects – 复数&#xff0c;表示可以一次输出多个对象。输出多个对象时&#xff0c;需要用 , 分隔。 sep – …

cas-server5.3自定义密码校验规则

前面几篇文章都是关于cas的,今天继续,cas有自己的一个加密配置.如果只是简单使用MD5或者SM3等加密算法进行加密的话,可以不需要再进行自定义操作,但是我们一般还会给用户密码加盐,这样的话原本的配置就不满足了,所以需要再自定义一个密码校验规则 实现PasswordEncoder接口 Pa…

数据报表的种类

根据报表使用频率不同&#xff0c;目的不同&#xff0c;使用群体不同&#xff0c;细化程度不同等情况&#xff0c;一般数据报表可以分为日常报表和临时报表&#xff0c;日常报表又分为管理报表和专题分析报表。 1. 日常报表 日常报表通常是指使用频率较高&#xff08;一般取3…

LED台灯控制芯片 LED调光芯片 LED驱动芯片AH6730

AH6730是一款专为LED台灯设计的多功能控制芯片。它采用电容式触摸控制&#xff0c;除了提供简单的开关控制功能外&#xff0c;还能实现从0到100或从100到0的无级调光&#xff0c;方便用户选择合适的亮度。该芯片的触摸板材兼容金属、亚克力板和硬塑料等材质。它具有两个通道的输…

Sketch macOS 支持m1 m2 Sketch 2023最新中文版

SketchUp Pro 2023是一款功能强大的三维建模软件&#xff0c;适用于建筑设计师、室内设计师、工程师和其他创意专业人士。以下是SketchUp Pro 2023的一些主要特点和功能&#xff1a; 三维建模&#xff1a;SketchUp Pro 2023允许用户以直观的方式创建三维模型。通过简单的绘图工…

【前端小技巧】如何使用 Eolink Apilkit 调用 Mock ?

在开发过程中&#xff0c;进度比较赶的情况下&#xff0c;前端人员当页面写完时&#xff0c;后台的接口还没写完&#xff0c;等要交付的时候后端才把接口给你&#xff0c;这个时候就很尴尬。 这个时候 Mock 就可以很好的解决这个问题&#xff0c;前端团队可以在 API 还没开发完…

CVE-2020-1938 Tomcat远程文件包含漏洞

漏洞简介 CVE-2020-1938是由长亭科技安全研究员发现的存在于 Tomcat 中的安全漏洞&#xff0c;由于 Tomcat AJP 协议设计上存在缺陷&#xff0c;攻击者通过 Tomcat AJP Connector 可以读取或包含 Tomcat 上所有 webapp 目录下的任意文件&#xff0c;例如可以读取 webapp 配置文…

whistle安卓手机抓包(图文详解)

1、安装node https://nodejs.org &#xff08;官网下载对应的node,一般推荐长期稳定版本 LTS&#xff09; 需要node的版本是大于 v0.10.0 查看自己本地node 版本号 node -v2、安装whistle npm i -g whistle3、开启whistle 补充说明&#xff1a; ● w2 stop&#xff1a;关闭…

ubuntu为可执行程序添加桌面图标

ubuntu为可执行程序添加桌面图标 1 在桌面目录&#xff0c;创建以.desktop为后缀的文件 cd ~/Desktop touch orb_slam.desktop 2 为desktopt添加执行权限 添加执行权限&#xff0c;才能实现双击运行&#xff0c;否则不能实现 chmod ax orb_slam.desktop3 编辑文件 ##(1)打…

Android+Appium自动化测试环境搭建及实操

1、Appium简介1.1 Appium概念1.2 Appium工作原理 2、Appium Server环境搭建2.1 Java JDK2.1.1 下载JDK2.1.2 运行exe安装JDK&#xff0c;设置安装路径2.1.3 设置环境变量2.1.4 验证安装结果 2.2 Android SDK2.2.1 下载安装Android SDK安装包2.2.2 下载platform-tools&#xff0…

php以半小时为单位,输出指定的时间范围

//可预订小时范围$hour [];for ($i$startHour*3600;$i<$endHour*3600;$i1800){//以半小时为单位输出$startHourItem date(H:i,strtotime(date(Y-m-d))$i);//小时开始$endHourItem date(H:i,strtotime(date(Y-m-d))$i1800);//当前时间再加半小时$hourItemStr $startHourI…

广州华锐互动:炼钢工厂VR仿真实训系统

随着科技的发展&#xff0c;我们的教育体系和职业培训方法也在迅速变化。其中&#xff0c;虚拟现实&#xff08;VR&#xff09;技术的出现为我们提供了一种全新的学习和培训方式。特别是在需要高度专业技能和安全性的领域&#xff0c;如钢铁冶炼。本文将探讨如何使用VR进行钢铁…

lark发消息艾特接口

首先访问"https://open.larksuite.com/api-explorer?apiNamebatch_get_id&projectcontact&resourceuser&versionv3"页面登录&#xff0c;然后点击左侧通过手机号或邮箱获取用户id&#xff0c;查询参数下面选择成员&#xff0c;搜索用户&#xff0c;点击…

探秘PMP和六西格玛的不同:哪一个能为你的职业生涯加分?

今天&#xff0c;我们将带你深入了解一项相对冷门但价值不菲的证书——六西格玛黑带。 可能你曾听说过PMP&#xff0c;但相比之下&#xff0c;六西格玛黑带的资源分享似乎较少&#xff0c;考试内容却更为广泛深入。这里&#xff0c;让我为你详细解析这一考试&#xff0c;带你进…