elementui 日历组件el-calendar使用总结

功能:

1.日历可以周视图、月视图切换;

2.点击月视图中日期可以切换到对应周视图;

3.点击周视图查看当日对应数据;

4.周、月视图状态下,点击前后按钮,分别切换对应上下的周、月;

5.点击回到今天,立即切回到周、月视图下对应的当日;

引用dayjs处理日期,结合el-calendar完美实现。

要注意的是,日历显示周的话,传的日期范围要按照计算所在星期,比如我们的需求是周日为每周起始日,那么就要给周日的日期和周六日期为起始日,月视图我不想再去计算日期范围了,就直接用了:value,注意用的不是v-model而是value,因为value是单向的,v-model是双向数据绑定了。

<template>
<div class="childContainer">
  <CompBar name="XX日历" iconName="rili.png" titleName="回到今天" @handleBarClick="nowCalendar">
  <div class="kalendar">
     <div class="kalendar-header">
        <span class="current-monuth">
            <i class="el-icon-caret-left" @click="showPrev"></i>
            <i class="el-icon-caret-right" @click="showNext"></i>
        </span>
        <el-radio-group v-model="monthYear" size="mini">
            <el-radio-button label="周"></el-radio-button>
            <el-radio-button label="月"></el-radio-button>
        </el-radio-group>
    </div>
    <CalendarMonth v-if="monthYear==='月'" :calendarValue="monthDate" :selectDay="dayDate" :dateList="dateList" @getPlanList="getplanList"></CalendarMonth>
    <CalendarWeek v-else :rangeArr="dateRange" :selectDay="dayDate" :dateList="dateList"         
@getPlanList="getplanList"></CalendarWeek>
  </div>
  <tabs :class="monthYear==='月'?'monthTabs':'weekTabs'" v-model="activePlan" v-loading="isLoading">
    <el-tab-pane name="tabApplyEndPlan">
//此处是个列表
</el-tab-pane>
    <el-tab-pane name="tabEndPlan"></el-tab-pane>
  </tabs>
</template>
// 此处省略组件、接口引入
import dayjs from 'dayjs';
var weekplugin = require('dayjs/plugin/weekday');
dayjs.extend(weekplugin)

// 此处省略,直接放核心代码
data(){
   return{
    activePlan:'tabApplyEndPlan',
    monthYear:'周', // 周、月视图切换,默认显示周
    monthDate:'', // 传后端参数 YYYY-MM,查视图上需要显示点的日期
    dayDate:'', // 传后端参数 YYYY-MM-DD,查视图下面对应的当日数据列表
    dateRange:[], // 周日历,传入周日历视图日期范围
    dateList:[], // 存放月数据,视图中需要显示点的日期
   }
},

watch:{
// 比较简单,直接省略代码了,记录下逻辑
// 监听 monthDate、dayDate 值的改变,调用对应接口
},

methods:{
showPrev() {
        // 上个月
        if (this.monthYear === '月') {
          this.monthDate = dayjs(this.monthDate).add(-1, 'month').format('YYYY-MM');
          // 需要判断当前选中日期是否属于当前月份
          let _dayDate = dayjs(this.dayDate).format('YYYY-MM');
          if (_dayDate === this.monthDate) {
            // 计算本周第一天
            let day1 = dayjs(this.dayDate).startOf('week').format('YYYY-MM-DD');
            // 计算本周最后一天
            let day2 = dayjs(this.dayDate).endOf('week').format('YYYY-MM-DD');
            this.dateRange = [day1, day2];
          } else {
            let day1 = dayjs(this.monthDate).startOf('month').startOf('week').format('YYYY-MM-DD');
            let day2 = dayjs(this.monthDate).startOf('month').endOf('week').format('YYYY-MM-DD');
            this.dateRange = [day1, day2]
          }
        }
        // 上星期
        if (this.monthYear === '周') {
          // 获取当前周视图
          let day1 = dayjs(this.dateRange[0]).add(-1, 'week').startOf('week').format('YYYY-MM-DD');
          let day2 = dayjs(this.dateRange[1]).add(-1, 'week').endOf('week').format('YYYY-MM-DD');
          this.monthDate = dayjs(this.dateRange[0]).add(-1, 'week').startOf('week').format('YYYY-MM');
          this.dateRange = [day1, day2]
        }
      }, 
showNext() {
        // 下个月
        if (this.monthYear === '月') {
          this.monthDate = dayjs(this.monthDate).add(1, 'month').format('YYYY-MM');
          // 需要判断当前选中日期是否属于当前月份
          let _dayDate = dayjs(this.dayDate).format('YYYY-MM');
          if (_dayDate === this.monthDate) {
            // 计算本周第一天
            let day1 = dayjs(this.dayDate).startOf('week').format('YYYY-MM-DD');
            // 计算本周最后一天
            let day2 = dayjs(this.dayDate).endOf('week').format('YYYY-MM-DD');
            this.dateRange = [day1, day2];
          } else {
            let day1 = dayjs(this.monthDate).endOf('month').startOf('week').format('YYYY-MM-DD');
            let day2 = dayjs(this.monthDate).endOf('month').endOf('week').format('YYYY-MM-DD');
            this.dateRange = [day1, day2]
          }
        }
        // 下星期
        if (this.monthYear === '周') {
          // 获取当前周视图
          let day1 = dayjs(this.dateRange[0]).add(1, 'week').startOf('week').format('YYYY-MM-DD');
          let day2 = dayjs(this.dateRange[1]).add(1, 'week').endOf('week').format('YYYY-MM-DD');
          this.monthDate = dayjs(this.dateRange[0]).add(1, 'week').startOf('week').format('YYYY-MM');
          this.dateRange = [day1, day2]
        }
      },
// 返回今日
     nowCalendar() {
      this.monthDate = dayjs(new Date()).format('YYYY-MM');
      this.dayDate = dayjs(new Date()).format('YYYY-MM-DD');
      let day1 = dayjs(new Date()).startOf('week').format('YYYY-MM-DD');
      let day2 = dayjs(new Date()).endOf('week').format('YYYY-MM-DD');
      this.dateRange = [day1, day2];
      this.activePlan = 'tabApplyEndPlan'
    },
// 周、月视图日期被点击处理方法
    getPlanList(date) {
      // console.log(this.monthYear)
      // console.log(date)
      this.dayDate = date.day;
      // 点击上、下月/周日期,不涉及视图的切换
      if (this.monthYear === '月') {
        if (date.type === 'next-month') {
          this.showNext()
        }
        if (date.type === 'prev-month') {
          this.showPrev()
        }
      }
      if (this.monthYear === '周') {
        let _month = dayjs(date.day).format('YYYY-MM');
        if (date.type === 'next-month') {
          if (_month !== this.monthDate) {
            this.monthDate = dayjs(date.day).format('YYYY-MM');
          }
        }
        if (date.type === 'prev-month') {
          if (_month !== this.monthDate) {
            this.monthDate = dayjs(date.day).format('YYYY-MM');
          }
        }
      }
      if (date.type === 'current-month') {
        this.monthYear = '周';
        // 计算本周第一天
        let day1 = dayjs(this.dayDate).startOf('week').format('YYYY-MM-DD');
        // 计算本周最后一天
        let day2 = dayjs(this.dayDate).endOf('week').format('YYYY-MM-DD');
        // 计算点击日期所在周第一天所属月
        this.monthDate = dayjs(day1).startOf('week').format('YYYY-MM');
        this.dateRange = [day1, day2];
      }
    },

}


自定义日历样式(没有用日历原先的头,全部自己重写的,还不错): 

::v-deep .kalendar {
    &-header {
      text-align: center;
      margin: 10px 16px 0 16px;

      .current-monuth {
        font-size: 16px;
        letter-spacing: 0;
        font-weight: 500;
        margin-left: 15%;
        color: #262626;
        font-family: PingFangSC-Medium;

        i {
          cursor: pointer;
        }
      }

      .el-radio-group {
        float: right;
      }

      .el-radio-button__orig-radio:checked + .el-radio-button__inner {
        background: #ffffff;
        box-shadow: -1px 0 0 0 transparent;
        border: 1px solid rgba(199, 0, 11, 1);
        font-family: PingFangSC-Medium;
        font-size: 12px;
        color: #c7000b;
        letter-spacing: -0.04px;
        font-weight: 500;
      }

      .el-radio-button__inner:hover {
        color: #c7000b;
      }
    }

    .calender-dot-box {
      width: 100%;
      bottom: -8px;
      position: absolute;

      span {
        width: 6px;
        height: 6px;
        margin-right: 3px;
        border-radius: 50%;
        display: inline-block;

        &:last-of-type {
          margin-right: 0;
        }
      }

      .endPlan {
        background-color: #d61212;
      }

      .applyEndPlan {
        background-color: #ffd100;
      }
    }

    .el-calendar {
      &__body {
        padding: 10px 16px;
      }

      .is-today {
        .el-calendar-day {
          .calender-date {
            width: 34px;
            height: 34px;
            margin: 0 auto;
            color: #ff534f;
            border-radius: 10px;
            background: #fff;
            box-shadow: none;
          }
        }
      }

      &__header {
        display: none;
      }

      .current {
        .el-calendar-day {
          color: #262626;
        }
      }

      .prev,
      .next {
        color: #bfbfbf;
      }

      &-day {
        padding: 0;
        font-weight: 700;
        font-size: 16px;
        letter-spacing: 0;
        text-align: center;
        position: relative;
        transition: color 0.3s;
        font-family: DINAlternate-Bold;
      }

      &-table {
        th {
          font-family: PingFangSC-Regular;
          font-size: 16px;
          color: #262626;
          letter-spacing: 0;
          text-align: center;
          line-height: 34px;
          font-weight: 400;
          padding: 0;

          &:last-of-type,
          &:first-of-type {
            color: #ff564e;
          }
        }

        td {
          border: none;

          &.is-selected {
            background-color: transparent;
          }
        }

        .el-calendar-day {
          height: 34px;
          line-height: 34px;

          &:hover {
            background-color: transparent;
          }

          .calendar-isSelected {
            width: 34px;
            height: 34px;
            margin: 0 auto;
            color: #fff;
            border-radius: 10px;
            background: #ff534f;
            box-shadow: 0px 0px 2px 0px rgba(238, 88, 64, 1);
          }
        }
      }
    }

再看看子组件里面,先看月的:

<template>
  <!-- 月日历 -->
  <el-calendar :value="calendarValue" :first-day-of-week="7" value-format="YYY-MM">
    <template slot="dateCell" slot-scope="{ date, data }">
      <div v-if="selectedDay === data.day" class="calendar-isSelected" @click="handleDate($event, date, data)">
        {{ date.getDate() }}
      </div>
      <div v-else class="calender-date" @click="handleDate($event, date, data)">
        {{ date.getDate() }}
      </div>
      <div class="calender-dot-box" @click="handleDate($event, date, data, 'dot')">
        <template v-for="(item) in dateLists">
          <span class="applyEndPlan" v-if="item.date === data.day && item.applyEndPlanNum > 0"></span>
          <span class="endPlan" v-if="item.date === data.day && item.endPlanNum > 0"></span>
        </template>
      </div>
    </template>
  </el-calendar>
</template>
<script>
export default {
  components: {},
  name: "CalendarMonth",
  props: {
    selectedDay: {
      type: String,
      default: "",
    },
    calendarValue: {
      type: String,
      default: new Date(),
    },
    dateList: {
      type: Array,
      default: () => {
        return [];
      },
    },
  },
  watch: {
    dateList: {
      handler(list) {
        this.dateLists = list;
      },
      immediate: true,
    },
  },
  data() {
    return { monthDate: this.calendarValue, dateLists: [] };
  },
  created() { },
  methods: {
    handleDate(e, date, data) {
      this.$emit("getPlanList", data);
    },
  },
};
</script>
<style lang="scss" scoped></style>

周日历组件:

<template>
  <!-- 周日历 -->
  <el-calendar :range="rangeArr" :first-day-of-week="7" value-format="YYY-MM">
    <template slot="dateCell" slot-scope="{date,data}">
      <div v-if="selectedDay === data.day" class="calendar-isSelected" @click="handleDate($event, date, data)">
        {{ date.getDate() }}</div> 
      <div v-else class="calender-date" @click="handleDate($event, date, data)">{{ date.getDate() }}</div>
      <div class="calender-dot-box" @click="handleDate($event, date, data)">
        <template v-for="(item) in dateList">
          <span class="applyEndPlan" v-if="item.date === data.day && item.applyEndPlanNum > 0"></span>
          <span class="endPlan" v-if="item.date === data.day && item.endPlanNum > 0"></span>
        </template>
      </div>
    </template>
  </el-calendar>
</template>
<script>
export default {
  components: {}, name: 'CalendarWeek', props: {
    selectedDay: {
      type: String, default: '',
    }, rangeArr: {
      type: Array,
      default: () => {
        return [];
      }
    }, dateList: {
      type: Array, default: () => {
        return [];
      }
    }
  }, data() {
    return {
    }
  }, created() {
  }, methods: {
    handleDate(e, date, data) {
      // console.log(e,date,data)
      this.$emit('getPlanList', data)
    },
  }
}</script>
<style lang="scss" scoped></style>

其实应该把日历组件二次封装一下,就不用单独再去写周、月日历子组件了,有空了可以试试。

不过不得不再吐槽一句,elementui的日历组件,给提供的API真心的少,功能很简单。。。

最终效果图:

月视图效果图:

月视图下,有时候会出现整整一行的灰色日期,看起来不是很美观,那么就需要操作dom,通过js判断,操作dom来处理。大概思路就是,先通过 document.querySelectorAll('.el-calendar-table__row') 获取到所有.el-calendar-table__row的元素节点lists,然后循环遍历这些节点,若其子元素class中含有.current,那么就说明是带有当月的日期,则不改变样式,若不含,则说明这整行都是前\后月的日期,那么就可以把该.el-calendar-table__row的css里面加上属性display:none。

周视图效果图: 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习】FaceChain-SuDe,免训练,AI换脸

https://arxiv.org/abs/2403.06775 FaceChain-SuDe: Building Derived Class to Inherit Category Attributes for One-shot Subject-Driven Generation 摘要 最近&#xff0c;基于主体驱动的生成技术由于其个性化文本到图像生成的能力&#xff0c;受到了广泛关注。典型的研…

Stable Diffusion - 光影魔法,SD中的光影控制(附模型)

今天继续分享SD中光影控制的运用和效果。 光影控制体验 — 这次介绍的光影控制效果如下&#xff1a; autumn lights&#xff1a;秋天光景&#xff0c;街景与人物服装也会变成秋装 spring lights&#xff1a;春天光景&#xff0c;街景与人物服装也会变成春装 summer lights…

【Python爬虫教程】第7篇-requests模块的cookies保存和使用

文章目录 为什么要保存cookiesrequests.utils工具类保存cookies到本地文件从本地文件解析cookies使用使用实践 为什么要保存cookies 保存cookies是避免每次都登录获取权限&#xff0c;一遍权限是有过期时间的&#xff0c;不需要每次重复登录&#xff0c;可以将cookies保存起来…

招聘难怎么破?这38个面试问题,助你精准筛选出适用人才!

对于专门负责招聘工作的人员来说&#xff0c;每天都有很多很多面试要应对&#xff0c;但你还不能敷衍&#xff0c;因为不能高效地挑选出合适的人才&#xff0c;你的招聘目标就没办法完成了。精准筛选你所需要的人才&#xff0c;跟面试官面试的时候提出的问题有很大关系。因为好…

29.【C语言】自定义函数

1、自定义详解 *提示&#xff1a;先看第12,19篇 例&#xff1a;写一个程序交换两个变量的值 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> void swap(int x, int y) {int z 0;z x;x y;y z; } int main() {int a 10;int b 20;swap(a, b);printf("%d…

【算法消费者行为】算法性能预期如何增强冲动性购买?—推文分享—2024-07-16

今天的推文主题是&#xff1a;【算法&消费者行为】 第一篇&#xff1a;如何通过管理多种刺激来优化客户体验&#xff1f;购买行为的驱动因素是隐性还是显性的消费者态度&#xff1f;第二篇&#xff1a;算法性能期望如何增强在线零售中的即兴购买行为。第三篇&#xff1a;社…

详解linux驱动框架(开篇)

该系列博客只是个人记录&#xff0c;笔者本人也是菜鸟&#xff0c;如果出现大量错误&#xff0c;欢迎留言评论&#xff0c;请不要进行人身攻击等行为。 让我们先从drivers/input/input.c入手&#xff0c;让我们想一想&#xff0c;当我们modprobe input1.ko时&#xff0c;内核会…

JuiceFS、Ceph 和 MinIO 结合使用

1. 流程图 将 JuiceFS、Ceph 和 MinIO 结合使用&#xff0c;可以充分利用 Ceph 的分布式存储能力、JuiceFS 的高性能文件系统特性&#xff0c;以及 MinIO 提供的对象存储接口。以下是一个方案&#xff0c;介绍如何配置和部署 JuiceFS 使用 Ceph 作为其底层存储&#xff0c;并通…

量化投资基础(三)之Fama-French 三因子模型(2)

点赞、关注&#xff0c;养成良好习惯 Life is short, U need Python 量化投资基础系列&#xff0c;不断更新中 1. 前言 Sharp&#xff08;1964&#xff09;&#xff0c;Lintner&#xff08;1965&#xff09;&#xff0c;Black&#xff08;1972&#xff09;的资本资产定价模型&…

【异常解决】Unable to start embedded Tomcat Nacos 启动报错

Unable to start embedded Tomcat Nacos 启动报错解决方案 一、背景描述二、原因分析三、解决方案 一、背景描述 Windows 本地启动 Nacos&#xff08;2.2.0&#xff09; 服务&#xff0c;控制台报错 Unable to start embedded Tomcat。 报错信息&#xff1a;Unable to start …

解决UniGUI中动态创建控件时,控件不按序显示的问题。

这两天遇到一个问题&#xff1a;我在UNIGUI中多批次动态创建控件&#xff0c;但是这些控件在显示时并没有按我想要的顺序排列。比如动态创建UnimContainerPanel面板&#xff0c;这个面板上放一些其它控件用于显示数据。在手机中从上到下按顺序显示出来&#xff0c;当第一批次时…

LabVIEW工业设备姿态监测系统

开发了一种基于LabVIEW的工业设备姿态监测系统&#xff0c;针对现有监测设备在适应性和反应时间上的不足&#xff0c;采用了LabVIEW软件和STM32微控制器&#xff0c;通过高精度姿态传感器实现了对设备姿态的快速准确监测&#xff0c;大大提高了工业作业的安全与效率。 项目背景…

Unable to obtain driver using Selenium Manager: Selenium Manager failed解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

jmeter-beanshell学习10-字符串补齐位数

每天都遇到新问题&#xff0c;今天又一个场景&#xff0c;一个字符串&#xff0c;如果不足11位&#xff0c;则左边补0&#xff0c;补够11位。 先要获取字符串长度&#xff0c;然后计算差多少位&#xff0c;补齐。今天又发现一个Object类型&#xff0c;这个类型有点厉害&#x…

【持续集成_05课_Linux部署SonarQube及结合开发项目部署】

一、Linux下安装SonarQube 1、安装sonarQube 前置条件&#xff1a;sonarQube不能使用root账号进行启动&#xff0c;所以需要创建普通用户及 其用户组 1&#xff09;创建组 2&#xff09;添加用户、组名、密码 3&#xff09;CMD上传qube文件-不能传到home路径下哦 4&#xff09…

探索Nuxt.js的useFetch:高效数据获取与处理指南

title: 探索Nuxt.js的useFetch&#xff1a;高效数据获取与处理指南 date: 2024/7/15 updated: 2024/7/15 author: cmdragon excerpt: 摘要&#xff1a;“探索Nuxt.js的useFetch&#xff1a;高效数据获取与处理指南”详述了Nuxt.js中useFetch函数的使用&#xff0c;包括基本用…

【前端4】表单 编辑模式、只读模式:HTML的`readonly`、el-input的v-if=“isEdit“

【前端】表单 编辑模式、只读模式 写在最前面一、什么是编辑模式与只读模式&#xff1f;应用场景编辑模式只读模式 二、编辑模式的实现例子只读模式的实现动态切换模式使用HTML的readonly属性使用Vue.js的v-if指令 三、前后端交互 <template>代码块两个字段独立是否直接与…

bash: ip: command not found

输入&#xff1a; ip addr 报错&#xff1a; bash: ip: command not found 报错解释&#xff1a; 这个错误表明在Docker容器中尝试执行ip addr命令时&#xff0c;找不到ip命令。这通常意味着iproute2包没有在容器的Linux发行版中安装或者没有正确地设置在容器的环境变量PA…

HackQuest介绍 web3 学习平台

HackQuest 官网地址&#xff1a; https://www.hackquest.io/zh HackQuest是一个专注于Web3技术教育的在线学习平台&#xff0c;旨在帮助全球开发者掌握区块链、加密货币和去中心化应用&#xff08;DApps&#xff09;领域的最新技能。该平台汇聚了超过14000名活跃开发者&#…

PyMongo Sort 操作:提升你的数据查询效率

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…