vue3自定义日历

news2024/11/26 20:27:00

原理

  • 现在的日历分为两种开头:
    1. '日', '一', '二', '三', '四', '五', '六'
    2. '一', '二', '三', '四', '五', '六', '日'
  • 一行7个日期,一共6行

  1. 其实不管哪种都一样,首先要确定第一行1号在哪个位置。
    如果说是 '日', '一', '二', '三', '四', '五', '六',那么getDay()是几,它前面就该补几位。当前是2023-7-1,这天是星期六,getDay() === 6前面补六天,如果是星期天getDay()===0前面不用补。这里就要去取上个月多少天了,减去这六天,就可以把前面的空补上。例如:上个月是6月,有30天,30-6+1=25,从25补到30就可以了。这里是需要判断闰年这些的,防止在2月取的不对。
  2. 第一行补多少天算完,直接循环当月的天数。7月是31天,直接循环渲染31天
  3. 现在算最后面还需要补多少天,6行一共42天,现在渲染了6+31=37天,还需要补42-37=5天。
2526272829301

在这里插入图片描述

  1. 其实不管哪种都一样,首先要确定第一行1号在哪个位置。
    如果说是 '一', '二', '三', '四', '五', '六','日',这里就有点小区别了。假设n=getDay(),应该补n-1天, 但是星期日例外,星期日的n=0但是它要补6天。当前是2023-7-1,这天是星期六,getDay() === 6前面补五天,如果是星期天getDay()===0前面补六天。
  2. 第一行补多少天算完,直接循环当月的天数。7月是31天,直接循环渲染31天
  3. 现在算最后面还需要补多少天,6行一共42天,现在渲染了5+31=36天,还需要补42-36=6天。
262728293012

在这里插入图片描述

源码

<template>
  <div>
    <div class="toolbar">
      <div class="btn" @click="preMonth">上一月</div>
      <div class="date">{{ currentYear }}年{{ currentMonth }}月</div>
      <div class="btn" @click="nextMonth">下一月</div>
    </div>
    <div class="container">
      <div v-for="(item, index) in header" :key="index" class="grid-item">{{ item }}</div>
      <div v-for="(item, index) in lastMonthSurplusDayArray" :key="index" class="grid-item">
        {{ item }}
      </div>
      <div
        v-for="(item, index) in currentMonthDayCount"
        :key="index"
        :class="[
          'grid-item',
          Math.random() * 30 < 10
            ? 'very-hot'
            : Math.random() * 30 < 20
            ? 'middle-hot'
            : 'normal-hot'
        ]"
      >
        {{ item }}
      </div>
      <div v-for="(item, index) in nextMonthSurplusDayArray" :key="index" class="grid-item">
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue'
// const header = reactive<string[]>(['日', '一', '二', '三', '四', '五', '六'])
const header = reactive<string[]>(['一', '二', '三', '四', '五', '六', '日'])
// 上个月剩余天数
const lastMonthSurplusDay = ref<number>(0)
const lastMonthSurplusDayArray = ref<number[]>([])
// 下个月剩余天数
const nextMonthSurplusDay = ref<number>(0)
const nextMonthSurplusDayArray = ref<number[]>([])
// 当前月份总天数
const currentMonthDayCount = ref<number>(0)
const currentYear = ref<number>(0)
const currentMonth = ref<number>(0)
const currentDate = ref<number>(0)
// 闰年
const leapMonthDay = reactive<number[]>([31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31])
// 平年
const normalMonthDay = reactive<number[]>([31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31])
// 是否为闰年
function isLeapYear(year: number) {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}
// 获取这个月1号的星期数
function getMonthFirstDay(year: number, month: number) {
  return new Date(year, month - 1, 1).getDay()
}
// 计算日期
function calculateDays() {
  // 获取本月第一天星期几(星期几就补多少个空)
  // lastMonthSurplusDay.value = getMonthFirstDay(currentYear.value, currentMonth.value)
  lastMonthSurplusDay.value =
    getMonthFirstDay(currentYear.value, currentMonth.value) === 0
      ? 6
      : getMonthFirstDay(currentYear.value, currentMonth.value) - 1
  // 获取当前月有多少天
  currentMonthDayCount.value = isLeapYear(currentYear.value)
    ? leapMonthDay[currentMonth.value - 1]
    : normalMonthDay[currentMonth.value - 1]
  let prevMonthLastDate = 0
  if (currentMonth.value === 1) {
    // 当前是1月还要用去年的去判断
    prevMonthLastDate = isLeapYear(currentYear.value - 1)
      ? leapMonthDay[leapMonthDay.length - 1]
      : normalMonthDay[normalMonthDay.length - 1]
  } else {
    prevMonthLastDate = isLeapYear(currentYear.value)
      ? leapMonthDay[currentMonth.value - 2]
      : normalMonthDay[currentMonth.value - 2]
  }
  // 获取还需要渲染多少天
  nextMonthSurplusDay.value = 42 - (lastMonthSurplusDay.value + currentMonthDayCount.value)
  const prevtemp = []
  const nexttemp = []
  for (let i = prevMonthLastDate - lastMonthSurplusDay.value + 1; i <= prevMonthLastDate; i++) {
    prevtemp.push(i)
  }
  for (let i = 1; i <= nextMonthSurplusDay.value; i++) {
    nexttemp.push(i)
  }
  lastMonthSurplusDayArray.value = prevtemp
  nextMonthSurplusDayArray.value = nexttemp
}
// 上个月
function preMonth() {
  if (currentMonth.value === 1) {
    currentMonth.value = 12
    --currentYear.value
  } else {
    --currentMonth.value
  }
  calculateDays()
}
// 下个月
function nextMonth() {
  if (currentMonth.value === 12) {
    currentMonth.value = 1
    ++currentYear.value
  } else {
    ++currentMonth.value
  }
  calculateDays()
}
// 获取当前日期
function getCurrentDate() {
  const d = new Date()
  const year = d.getFullYear()
  const month = d.getMonth() + 1
  const date = d.getDate()
  return {
    year,
    month,
    date
  }
}
// 初始化日历
function initCalendar() {
  const { year, month, date } = getCurrentDate()
  currentYear.value = year
  currentMonth.value = month
  currentDate.value = date
  calculateDays()
}
onMounted(() => {
  initCalendar()
})
</script>

<style scoped>
.toolbar {
  display: flex;
  width: 100%;
  height: 50px;
}

.toolbar .date {
  flex: 1;
  color: #333;
  font-size: 14px;
  font-weight: bold;
  text-align: center;
  line-height: 30px;
  border-top: 1px solid #eee;
  padding: 10px;
  box-sizing: border-box;
}
.toolbar .btn {
  flex: 1;
  color: #1d84f6;
  text-align: center;
  line-height: 30px;
  border-top: 1px solid #eee;
  border-left: 1px solid #eee;
  border-right: 1px solid #eee;
  padding: 10px;
  box-sizing: border-box;
}
.container {
  display: grid;
  box-sizing: border-box;
  grid-template-columns: auto auto auto auto auto auto auto;
  border-top: 1px solid #eee;
  border-left: 1px solid #eee;
  border-right: 1px solid #eee;
}
.grid-item {
  width: 50px;
  height: 50px;
  line-height: 50px;
  border-bottom: 1px solid #eee;
  border-right: 1px solid #eee;
  font-size: 14px;
  text-align: center;
}

.grid-item:nth-child(7n) {
  border-right: none;
}

.very-hot {
  background-color: #e10231;
}
.middle-hot {
  background-color: #fe4806;
}
.normal-hot {
  background-color: #ffb508;
}
</style>

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

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

相关文章

了解Unity编辑器之组件篇UI(一)

UI组件&#xff1a;提供了用户交互&#xff0c;信息展示&#xff0c;用户导航等功能 一、Button&#xff1a;用于响应用户的点击事件 1.Interactable&#xff08;可交互&#xff09;&#xff1a;该属性控制按钮是否可以与用户交互&#xff0c;如果禁用则按钮无法被点击。可以通…

为什么TM服务器要安装php~

"想像力比知识更重要。因为知识是有限的&#xff0c;而想像力是无限&#xff0c;它包含了一切&#xff0c;推动着进步&#xff0c;是人类进化的源泉。 -- 爱因斯坦 为什么服务器要安装php~ 服务器为什么安装PHP (2023年) 导读&#xff1a;今天来给各位分享关于服务器为什么…

List有值二次转换给其他对象报null

List<PlatformUsersData> listData platformUsersMapper.selectPlatformUserDataById(data); users.setPlatformUsersData(listData);为什么listData 有值&#xff0c;users.getPlatformUsersData&#xff08;&#xff09;仍然为空在这段代码中&#xff0c;我们假设listD…

初识C++ ------ 引用、内联函数、auto关键字、基于范围的for循环、指针空值

文章目录 引用特点引用和指针的区别 内联函数概念 auto 关键字基于范围的for循环指针空值 nullptr &#xff08;C11&#xff09; 引用 特点 传引用返回&#xff1a;提高了效率&#xff0c;可以修改返回对象&#xff0c;传引用传参&#xff1a;提高效率&#xff0c;输出型参数。…

解密动态内存管理的奥秘(含内存4个函数)

目录 一.为什么存在动态内存管理 二.动态内存函数的介绍 1. malloc函数&#xff08;memory alloc 内存开辟&#xff09; 函数介绍&#xff1a; malloc函数使用举例代码&#xff1a; 2.free&#xff08;释放&#xff09; 函数介绍&#xff1a; 代码的示例&#xff1a…

Linux 网络通信epoll详解( 10 ) -【Linux通信架构系列 】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the…

《网络是怎样连接的》(二.1)

(83条消息) 《网络是怎样连接的》&#xff08;一&#xff09;_qq_38480311的博客-CSDN博客 本文主要取材于 《网络是怎样连接的》 第二章。 目录 &#xff08;1&#xff09;创建套接字 &#xff08;2&#xff09;连接服务器 &#xff08;3&#xff09;收发数据 &#xf…

文本预处理——文本处理的基本方法

目录 什么是分词jieba分词特性精确模式分词全模式分词搜索引擎模式分词使用用户自定义词典 命名实体识别词性标注 什么是分词 jieba分词特性 精确模式分词 import jieba content工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作 print(jieba.lcut(co…

《零基础入门学习Python》第055讲:论一只爬虫的自我修养3:隐藏

0. 请写下这一节课你学习到的内容&#xff1a;格式不限&#xff0c;回忆并复述是加强记忆的好方式&#xff01; 上节课我们说过了&#xff0c;有一些网站比较痛恨爬虫程序&#xff0c;它们不喜欢被程序所访问&#xff0c;所以它们会检查链接的来源&#xff0c;如果说来源不是正…

ONGUI

public class ONGUI : MonoBehaviour {private void OnGUI() {GUI.Label(new Rect(0,0,100,250),"ONGUI");} }说明是以左上角为原点来算的

Spring Cloud【服务网关Gateway(三大核心概念、入门案例、路由规则 、Java API构建路由、动态路由、断言功能详解)】(六)

目录 服务网关Gateway_三大核心概念 服务网关Gateway_入门案例 服务网关Gateway_路由规则 服务网关Gateway_Java API构建路由 服务网关Gateway_动态路由 服务网关Gateway_断言功能详解 服务网关Gateway_三大核心概念 路由(Route) 这是网关的基本构建块。它由一个ID&am…

小程序自定义导航栏

效果图 代码 app.json文件下 "window":{"navigationStyle": "custom" //增加此属性},app.js文件 //计算高度 App({onLaunch() {wx.getSystemInfo({ // 获取设备信息success: (res) > {this.globalData.systeminfo res//导航栏let statusB…

springboot整合quartz通过数据库配置任务调度简单办法

简介 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;它可以与J2EE与J2SE应用程序相结合也可以单独使用。在java企业级应用中&#xff0c;Quartz是使用最广泛的定时调度框架。 在Quartz中的主要概念&#xff1a; Scheduler&#xff1a;调度任务…

C语言中文件的读写

不争输赢&#xff0c;只问对错 文章目录 一、文件的概述 二、什么是读写文件 三、文件处理的函数 1.文件的打开与关闭 2.文件的顺序读写 文件的顺序读写相关函数 scanf 和 printf 家族的对比及其区分 3.文件的随机读写 文件的随机读写函数 四、文件缓冲区 五…

【el-tree查询并高亮】vue使用el-tree组件,搜索展开并选中对应节点,高亮搜索的关键字,过滤后高亮关键字,两种方法

第一种&#xff08;直接展开并高亮关键字&#xff09; 效果图这样的&#xff0c;会把所有的有这些关键字的节点都展开 代码&#xff1a; 这里的逻辑就是通过递归循环把所有和关键字匹配的节点筛选出来 然后通过setCheckedKeys方法把他展开选中 然后通过filterReal把关键字高亮…

Hadoop——DataGrip连接MySQL|Hive

1、下载 DataGrip下载&#xff1a;DataGrip: The Cross-Platform IDE for Databases & SQL by JetBrains 2、破解 破解链接&#xff1a;https://www.cnblogs.com/xiaohuhu/p/17218430.html 3、启动环境 启动Hadoop&#xff1a;到Hadoop的sbin目录下右键管理员身份运行…

数学建模学习(2):数学建模各类常用的算法全解析

一、评价类算法 常见的评价算法 1.层次分析法 基本思想 是定性与定量相结合的多准则决策、评价方法。将决策的有关元素分解成 目标层、准则层和方案层 &#xff0c;并通过人们的 判断对决策方案的 优劣进行排序 &#xff0c;在此基础上进行定性和定量分析。它把人的思维过程…

预处理详解

目录 一、预定义符号 二、#define 1.认识#define 2.使用#define 2.1#define定义常量 2.2#define定义宏 2.3#define的替换规则 三、宏定义的其他内容 1.#和## 1.1# 1.2## 2.宏的副作用 3.宏的命名规则 4.undef 5.条件编译 一、预定义符号 #include<stdio.h> int…

通过FPGA实现基于RS232串口的指令发送并控制显示器中目标位置

目录 1.算法理论概述 串口通信模块 指令解析模块 位置控制模块 显示器驱动模块 2.部分核心程序 3.算法运行软件版本 4.算法运行效果图预览 5.算法完整程序工程 1.算法理论概述 通过FPGA实现基于RS232串口的指令发送并控制显示器中目标位置是一种常见的应用场景&#x…

双向不循环链表的认识和基础操作(节点创建,头插头删,尾插尾删,输出和逆置)

头定义&#xff1a; typedef char datatype[20];//datatypechar[20] typedef struct Node {//数据域 数据元素datatype data;//指针域 下一个节点地址struct Node* next;//指针域 上一个节点地址struct Node* prev; }*DoubleLink; 创建节点&#xff1a; DoubleLink create_n…