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

打印 上一主题 下一主题

主题 492|帖子 492|积分 1476

功能:
1.日历可以周视图、月视图切换;
2.点击月视图中日期可以切换到对应周视图;
3.点击周视图检察当日对应数据;
4.周、月视图状态下,点击前后按钮,分别切换对应上下的周、月;
5.点击回到今天,立即切回到周、月视图下对应的当日;
引用dayjs处理日期,联合el-calendar完美实现。
要留意的是,日历体现周的话,传的日期范围要按照盘算地点星期,好比我们的需求是周日为每周起始日,那么就要给周日的日期和周六日期为起始日,月视图我不想再去盘算日期范围了,就直接用了:value,留意用的不是v-model而是value,因为value是单向的,v-model是双向数据绑定了。

  1. <template>
  2. <div class="childContainer">
  3.   <CompBar name="XX日历" iconName="rili.png" titleName="回到今天" @handleBarClick="nowCalendar">
  4.   <div class="kalendar">
  5.      <div class="kalendar-header">
  6.         <span class="current-monuth">
  7.             <i class="el-icon-caret-left" @click="showPrev"></i>
  8.             <i class="el-icon-caret-right" @click="showNext"></i>
  9.         </span>
  10.         <el-radio-group v-model="monthYear" size="mini">
  11.             <el-radio-button label="周"></el-radio-button>
  12.             <el-radio-button label="月"></el-radio-button>
  13.         </el-radio-group>
  14.     </div>
  15.     <CalendarMonth v-if="monthYear==='月'" :calendarValue="monthDate" :selectDay="dayDate" :dateList="dateList" @getPlanList="getplanList"></CalendarMonth>
  16.     <CalendarWeek v-else :rangeArr="dateRange" :selectDay="dayDate" :dateList="dateList"         
  17. @getPlanList="getplanList"></CalendarWeek>
  18.   </div>
  19.   <tabs :class="monthYear==='月'?'monthTabs':'weekTabs'" v-model="activePlan" v-loading="isLoading">
  20.     <el-tab-pane name="tabApplyEndPlan">
  21. //此处是个列表
  22. </el-tab-pane>
  23.     <el-tab-pane name="tabEndPlan"></el-tab-pane>
  24.   </tabs>
  25. </template>
  26. // 此处省略组件、接口引入
  27. import dayjs from 'dayjs';
  28. var weekplugin = require('dayjs/plugin/weekday');
  29. dayjs.extend(weekplugin)
  30. // 此处省略,直接放核心代码
  31. data(){
  32.    return{
  33.     activePlan:'tabApplyEndPlan',
  34.     monthYear:'周', // 周、月视图切换,默认显示周
  35.     monthDate:'', // 传后端参数 YYYY-MM,查视图上需要显示点的日期
  36.     dayDate:'', // 传后端参数 YYYY-MM-DD,查视图下面对应的当日数据列表
  37.     dateRange:[], // 周日历,传入周日历视图日期范围
  38.     dateList:[], // 存放月数据,视图中需要显示点的日期
  39.    }
  40. },
  41. watch:{
  42. // 比较简单,直接省略代码了,记录下逻辑
  43. // 监听 monthDate、dayDate 值的改变,调用对应接口
  44. },
  45. methods:{
  46. showPrev() {
  47.         // 上个月
  48.         if (this.monthYear === '月') {
  49.           this.monthDate = dayjs(this.monthDate).add(-1, 'month').format('YYYY-MM');
  50.           // 需要判断当前选中日期是否属于当前月份
  51.           let _dayDate = dayjs(this.dayDate).format('YYYY-MM');
  52.           if (_dayDate === this.monthDate) {
  53.             // 计算本周第一天
  54.             let day1 = dayjs(this.dayDate).startOf('week').format('YYYY-MM-DD');
  55.             // 计算本周最后一天
  56.             let day2 = dayjs(this.dayDate).endOf('week').format('YYYY-MM-DD');
  57.             this.dateRange = [day1, day2];
  58.           } else {
  59.             let day1 = dayjs(this.monthDate).startOf('month').startOf('week').format('YYYY-MM-DD');
  60.             let day2 = dayjs(this.monthDate).startOf('month').endOf('week').format('YYYY-MM-DD');
  61.             this.dateRange = [day1, day2]
  62.           }
  63.         }
  64.         // 上星期
  65.         if (this.monthYear === '周') {
  66.           // 获取当前周视图
  67.           let day1 = dayjs(this.dateRange[0]).add(-1, 'week').startOf('week').format('YYYY-MM-DD');
  68.           let day2 = dayjs(this.dateRange[1]).add(-1, 'week').endOf('week').format('YYYY-MM-DD');
  69.           this.monthDate = dayjs(this.dateRange[0]).add(-1, 'week').startOf('week').format('YYYY-MM');
  70.           this.dateRange = [day1, day2]
  71.         }
  72.       },
  73. showNext() {
  74.         // 下个月
  75.         if (this.monthYear === '月') {
  76.           this.monthDate = dayjs(this.monthDate).add(1, 'month').format('YYYY-MM');
  77.           // 需要判断当前选中日期是否属于当前月份
  78.           let _dayDate = dayjs(this.dayDate).format('YYYY-MM');
  79.           if (_dayDate === this.monthDate) {
  80.             // 计算本周第一天
  81.             let day1 = dayjs(this.dayDate).startOf('week').format('YYYY-MM-DD');
  82.             // 计算本周最后一天
  83.             let day2 = dayjs(this.dayDate).endOf('week').format('YYYY-MM-DD');
  84.             this.dateRange = [day1, day2];
  85.           } else {
  86.             let day1 = dayjs(this.monthDate).endOf('month').startOf('week').format('YYYY-MM-DD');
  87.             let day2 = dayjs(this.monthDate).endOf('month').endOf('week').format('YYYY-MM-DD');
  88.             this.dateRange = [day1, day2]
  89.           }
  90.         }
  91.         // 下星期
  92.         if (this.monthYear === '周') {
  93.           // 获取当前周视图
  94.           let day1 = dayjs(this.dateRange[0]).add(1, 'week').startOf('week').format('YYYY-MM-DD');
  95.           let day2 = dayjs(this.dateRange[1]).add(1, 'week').endOf('week').format('YYYY-MM-DD');
  96.           this.monthDate = dayjs(this.dateRange[0]).add(1, 'week').startOf('week').format('YYYY-MM');
  97.           this.dateRange = [day1, day2]
  98.         }
  99.       },
  100. // 返回今日
  101.      nowCalendar() {
  102.       this.monthDate = dayjs(new Date()).format('YYYY-MM');
  103.       this.dayDate = dayjs(new Date()).format('YYYY-MM-DD');
  104.       let day1 = dayjs(new Date()).startOf('week').format('YYYY-MM-DD');
  105.       let day2 = dayjs(new Date()).endOf('week').format('YYYY-MM-DD');
  106.       this.dateRange = [day1, day2];
  107.       this.activePlan = 'tabApplyEndPlan'
  108.     },
  109. // 周、月视图日期被点击处理方法
  110.     getPlanList(date) {
  111.       // console.log(this.monthYear)
  112.       // console.log(date)
  113.       this.dayDate = date.day;
  114.       // 点击上、下月/周日期,不涉及视图的切换
  115.       if (this.monthYear === '月') {
  116.         if (date.type === 'next-month') {
  117.           this.showNext()
  118.         }
  119.         if (date.type === 'prev-month') {
  120.           this.showPrev()
  121.         }
  122.       }
  123.       if (this.monthYear === '周') {
  124.         let _month = dayjs(date.day).format('YYYY-MM');
  125.         if (date.type === 'next-month') {
  126.           if (_month !== this.monthDate) {
  127.             this.monthDate = dayjs(date.day).format('YYYY-MM');
  128.           }
  129.         }
  130.         if (date.type === 'prev-month') {
  131.           if (_month !== this.monthDate) {
  132.             this.monthDate = dayjs(date.day).format('YYYY-MM');
  133.           }
  134.         }
  135.       }
  136.       if (date.type === 'current-month') {
  137.         this.monthYear = '周';
  138.         // 计算本周第一天
  139.         let day1 = dayjs(this.dayDate).startOf('week').format('YYYY-MM-DD');
  140.         // 计算本周最后一天
  141.         let day2 = dayjs(this.dayDate).endOf('week').format('YYYY-MM-DD');
  142.         // 计算点击日期所在周第一天所属月
  143.         this.monthDate = dayjs(day1).startOf('week').format('YYYY-MM');
  144.         this.dateRange = [day1, day2];
  145.       }
  146.     },
  147. }
复制代码
自定义日历样式(没有用日历原先的头,全部自己重写的,还不错): 
  1. ::v-deep .kalendar {
  2.     &-header {
  3.       text-align: center;
  4.       margin: 10px 16px 0 16px;
  5.       .current-monuth {
  6.         font-size: 16px;
  7.         letter-spacing: 0;
  8.         font-weight: 500;
  9.         margin-left: 15%;
  10.         color: #262626;
  11.         font-family: PingFangSC-Medium;
  12.         i {
  13.           cursor: pointer;
  14.         }
  15.       }
  16.       .el-radio-group {
  17.         float: right;
  18.       }
  19.       .el-radio-button__orig-radio:checked + .el-radio-button__inner {
  20.         background: #ffffff;
  21.         box-shadow: -1px 0 0 0 transparent;
  22.         border: 1px solid rgba(199, 0, 11, 1);
  23.         font-family: PingFangSC-Medium;
  24.         font-size: 12px;
  25.         color: #c7000b;
  26.         letter-spacing: -0.04px;
  27.         font-weight: 500;
  28.       }
  29.       .el-radio-button__inner:hover {
  30.         color: #c7000b;
  31.       }
  32.     }
  33.     .calender-dot-box {
  34.       width: 100%;
  35.       bottom: -8px;
  36.       position: absolute;
  37.       span {
  38.         width: 6px;
  39.         height: 6px;
  40.         margin-right: 3px;
  41.         border-radius: 50%;
  42.         display: inline-block;
  43.         &:last-of-type {
  44.           margin-right: 0;
  45.         }
  46.       }
  47.       .endPlan {
  48.         background-color: #d61212;
  49.       }
  50.       .applyEndPlan {
  51.         background-color: #ffd100;
  52.       }
  53.     }
  54.     .el-calendar {
  55.       &__body {
  56.         padding: 10px 16px;
  57.       }
  58.       .is-today {
  59.         .el-calendar-day {
  60.           .calender-date {
  61.             width: 34px;
  62.             height: 34px;
  63.             margin: 0 auto;
  64.             color: #ff534f;
  65.             border-radius: 10px;
  66.             background: #fff;
  67.             box-shadow: none;
  68.           }
  69.         }
  70.       }
  71.       &__header {
  72.         display: none;
  73.       }
  74.       .current {
  75.         .el-calendar-day {
  76.           color: #262626;
  77.         }
  78.       }
  79.       .prev,
  80.       .next {
  81.         color: #bfbfbf;
  82.       }
  83.       &-day {
  84.         padding: 0;
  85.         font-weight: 700;
  86.         font-size: 16px;
  87.         letter-spacing: 0;
  88.         text-align: center;
  89.         position: relative;
  90.         transition: color 0.3s;
  91.         font-family: DINAlternate-Bold;
  92.       }
  93.       &-table {
  94.         th {
  95.           font-family: PingFangSC-Regular;
  96.           font-size: 16px;
  97.           color: #262626;
  98.           letter-spacing: 0;
  99.           text-align: center;
  100.           line-height: 34px;
  101.           font-weight: 400;
  102.           padding: 0;
  103.           &:last-of-type,
  104.           &:first-of-type {
  105.             color: #ff564e;
  106.           }
  107.         }
  108.         td {
  109.           border: none;
  110.           &.is-selected {
  111.             background-color: transparent;
  112.           }
  113.         }
  114.         .el-calendar-day {
  115.           height: 34px;
  116.           line-height: 34px;
  117.           &:hover {
  118.             background-color: transparent;
  119.           }
  120.           .calendar-isSelected {
  121.             width: 34px;
  122.             height: 34px;
  123.             margin: 0 auto;
  124.             color: #fff;
  125.             border-radius: 10px;
  126.             background: #ff534f;
  127.             box-shadow: 0px 0px 2px 0px rgba(238, 88, 64, 1);
  128.           }
  129.         }
  130.       }
  131.     }
复制代码
再看看子组件里面,先看月的:
  1. <template>
  2.   <!-- 月日历 -->
  3.   <el-calendar :value="calendarValue" :first-day-of-week="7" value-format="YYY-MM">
  4.     <template slot="dateCell" slot-scope="{ date, data }">
  5.       <div v-if="selectedDay === data.day" class="calendar-isSelected" @click="handleDate($event, date, data)">
  6.         {{ date.getDate() }}
  7.       </div>
  8.       <div v-else class="calender-date" @click="handleDate($event, date, data)">
  9.         {{ date.getDate() }}
  10.       </div>
  11.       <div class="calender-dot-box" @click="handleDate($event, date, data, 'dot')">
  12.         <template v-for="(item) in dateLists">
  13.           <span class="applyEndPlan" v-if="item.date === data.day && item.applyEndPlanNum > 0"></span>
  14.           <span class="endPlan" v-if="item.date === data.day && item.endPlanNum > 0"></span>
  15.         </template>
  16.       </div>
  17.     </template>
  18.   </el-calendar>
  19. </template>
  20. <script>
  21. export default {
  22.   components: {},
  23.   name: "CalendarMonth",
  24.   props: {
  25.     selectedDay: {
  26.       type: String,
  27.       default: "",
  28.     },
  29.     calendarValue: {
  30.       type: String,
  31.       default: new Date(),
  32.     },
  33.     dateList: {
  34.       type: Array,
  35.       default: () => {
  36.         return [];
  37.       },
  38.     },
  39.   },
  40.   watch: {
  41.     dateList: {
  42.       handler(list) {
  43.         this.dateLists = list;
  44.       },
  45.       immediate: true,
  46.     },
  47.   },
  48.   data() {
  49.     return { monthDate: this.calendarValue, dateLists: [] };
  50.   },
  51.   created() { },
  52.   methods: {
  53.     handleDate(e, date, data) {
  54.       this.$emit("getPlanList", data);
  55.     },
  56.   },
  57. };
  58. </script>
  59. <style lang="scss" scoped></style>
复制代码
周日历组件:
  1. <template>
  2.   <!-- 周日历 -->
  3.   <el-calendar :range="rangeArr" :first-day-of-week="7" value-format="YYY-MM">
  4.     <template slot="dateCell" slot-scope="{date,data}">
  5.       <div v-if="selectedDay === data.day" class="calendar-isSelected" @click="handleDate($event, date, data)">
  6.         {{ date.getDate() }}</div>
  7.       <div v-else class="calender-date" @click="handleDate($event, date, data)">{{ date.getDate() }}</div>
  8.       <div class="calender-dot-box" @click="handleDate($event, date, data)">
  9.         <template v-for="(item) in dateList">
  10.           <span class="applyEndPlan" v-if="item.date === data.day && item.applyEndPlanNum > 0"></span>
  11.           <span class="endPlan" v-if="item.date === data.day && item.endPlanNum > 0"></span>
  12.         </template>
  13.       </div>
  14.     </template>
  15.   </el-calendar>
  16. </template>
  17. <script>
  18. export default {
  19.   components: {}, name: 'CalendarWeek', props: {
  20.     selectedDay: {
  21.       type: String, default: '',
  22.     }, rangeArr: {
  23.       type: Array,
  24.       default: () => {
  25.         return [];
  26.       }
  27.     }, dateList: {
  28.       type: Array, default: () => {
  29.         return [];
  30.       }
  31.     }
  32.   }, data() {
  33.     return {
  34.     }
  35.   }, created() {
  36.   }, methods: {
  37.     handleDate(e, date, data) {
  38.       // console.log(e,date,data)
  39.       this.$emit('getPlanList', data)
  40.     },
  41.   }
  42. }</script>
  43. <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。
周视图结果图: 



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

涛声依旧在

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表