功能:
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];
- }
- },
- }
复制代码 自定义日历样式(没有用日历原先的头,全部自己重写的,还不错):
再看看子组件里面,先看月的:
- <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。
周视图结果图:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |