vue h5日历组件
小菜一枚(white) 人气:0日历样式自定义
日历组件
<template> <section class="wh_container"> <div class="wh_content_all"> <div class="wh_top_changge"> <li @click="PreMonth(myDate,false)"> <div class="wh_jiantou1"></div> </li> <li class="wh_content_li">{{dateTop}}</li> <li @click="NextMonth(myDate,false)"> <div class="wh_jiantou2"></div> </li> </div> <div class="wh_content"> <div class="wh_content_item" v-for="(tag,index) in textTop" :key="index"> <div class="wh_top_tag">{{tag}}</div> </div> </div> <div class="wh_content"> <div class="wh_content_item" v-for="(item,index) in list" @click="clickDay(item,index)" :key="index" > <!-- <div class="wh_item_date" :class="item.isToday?'wh_isToday':item.isPreDay?'wh_chose_day':item.isChosedDay?'wh_chose_day':''" >{{item.id}}</div>--> <div class="wh_item_date" v-bind:class="[{ wh_isMark: item.isMark}, {wh_other_dayhide:item.otherMonth!=='nowMonth'}, {wh_want_dayhide:item.dayHide}, {wh_isToday:item.isToday}, {wh_chose_day:item.chooseDay},setClass(item)]" >{{item.id}}</div> </div> </div> </div> </section> </template> <script> import moment from "moment"; import timeUtil from "./calendar"; import Vue from "vue"; export default { data() { return { myDate: [], list: [], historyChose: [], dateTop: "", }; }, props: { rangeDate: { type: Array, default: () => [], }, markDate: { type: Array, default: () => [], }, markDateMore: { type: Array, default: () => [], }, textTop: { type: Array, default: () => ["一", "二", "三", "四", "五", "六", "日"], }, sundayStart: { type: Boolean, default: () => false, }, agoDayHide: { type: String, default: `0`, }, futureDayHide: { type: String, default: `2554387200`, }, }, created() { this.intStart(); // 获取今日的日期 var curDate = new Date(); var preDate = Date.parse(new Date(curDate.getTime() - 24 * 60 * 60 * 1000)); //前一天 this.myDate = new Date(preDate); console.log(this.rangeDate); }, methods: { intStart() { timeUtil.sundayStart = this.sundayStart; }, setClass(data) { // console.log('data',data) let obj = {}; obj[data.markClassName] = data.markClassName; return obj; }, // 点击选择的日期 clickDay: function (item, index) { console.log("in", "kkkkkk", item); if (item.otherMonth === "nowMonth" && !item.dayHide) { console.log("in", "kkkkkk"); this.getList(this.myDate, item.date); } if (item.otherMonth !== "nowMonth") { item.otherMonth === "preMonth" ? this.PreMonth(item.date) : this.NextMonth(item.date); } }, // 选择月份 ChoseMonth: function (date, isChosedDay = true) { date = timeUtil.dateFormat(date); this.myDate = new Date(date); this.$emit("changeMonth", timeUtil.dateFormat(this.myDate)); if (isChosedDay) { this.getList(this.myDate, date, isChosedDay); } else { this.getList(this.myDate); } }, // 上一个月的切换 PreMonth: function (date, isChosedDay = true) { date = timeUtil.dateFormat(date); this.myDate = timeUtil.getOtherMonth(this.myDate, "preMonth"); this.$emit("changeMonth", timeUtil.dateFormat(this.myDate)); if (isChosedDay) { this.getList(this.myDate, date, isChosedDay); } else { this.getList(this.myDate); } }, // 下一个月的切换 NextMonth: function (date, isChosedDay = true) { date = timeUtil.dateFormat(date); this.myDate = timeUtil.getOtherMonth(this.myDate, "nextMonth"); this.$emit("changeMonth", timeUtil.dateFormat(this.myDate)); if (isChosedDay) { this.getList(this.myDate, date, isChosedDay); } else { this.getList(this.myDate); } }, // 数据格式化的处理 forMatArgs: function () { let markDate = this.markDate; let markDateMore = this.markDateMore; let rangeDate = this.rangeDate; markDate = markDate.map((k) => { return timeUtil.dateFormat(k); }); rangeDate = rangeDate.map((k) => { return timeUtil.dateFormat(k); }); return [markDate, markDateMore, rangeDate]; }, // 日期表格的的样式初始化 getList: function (date, chooseDay, isChosedDay = true) { console.log(date, chooseDay, "listCanshu", this.rangeDate); const [markDate, markDateMore, rangeDate] = this.forMatArgs(); // 标签 this.dateTop = `${date.getFullYear()}年${date.getMonth() + 1}月`; // 顶部的头 let arr = timeUtil.getMonthList(this.myDate); // 获取当前日期的整个月份 for (let i = 0; i < arr.length; i++) { let markClassName = ""; let k = arr[i]; k.chooseDay = false; const nowTime = k.date; //当前遍历的哪个时间 const t = new Date(nowTime).getTime() / 1000; //看每一天的class for (const c of markDateMore) { if (c.date === nowTime) { markClassName = c.className || ""; } } //标记选中某些天 设置class k.markClassName = markClassName; k.isMark = markDate.indexOf(nowTime) > -1; if (this.rangeDate) { k.isMark = rangeDate.indexOf(nowTime) > -1; } //无法选中某天 k.dayHide = t < this.agoDayHide || t > this.futureDayHide; if (k.isToday) { this.$emit("isToday", nowTime); } // if(this.rangeDate.length){ // if(timeUtil.dateFormat(moment(this.rangeDate[0]).format("YYYY-MM-DD"))===nowTime || timeUtil.dateFormat(moment(this.rangeDate[6]).format("YYYY-MM-DD"))===nowTime){ // k.chooseDay = true; // }else{ // k.chooseDay = false; // } // } var curDate = new Date(); var preDate = Date.parse( new Date(curDate.getTime() - 24 * 60 * 60 * 1000) ); //前一天 const preDay = timeUtil.dateFormat( moment(preDate).format("YYYY-MM-DD") ); // 处理默认当月的的前一天是被选中 if (nowTime === preDay && !chooseDay && !this.rangeDate.length) { k.chooseDay = true; } else { k.chooseDay = false; } let flag = !k.dayHide && k.otherMonth === "nowMonth"; if (chooseDay && chooseDay === nowTime && flag) { this.$emit("choseDay", nowTime); this.historyChose.push(nowTime); console.log(this.historyChose); if (this.rangeDate.length) { k.chooseDay = false; } else { k.chooseDay = true; } } else if ( this.historyChose[this.historyChose.length - 1] === nowTime && !chooseDay && flag ) { console.log("进来这里了"); // 处理日月的切换 if (this.rangeDate.length) { k.chooseDay = false; } else { if (this.chooseDay) { k.chooseDay = true; } else { k.chooseDay = false; } } } } this.list = arr; }, }, mounted() { this.getList(this.myDate); }, watch: { rangeDate: { handler(val, oldVal) { this.getList(this.myDate); }, deep: true, }, markDate: { handler(val, oldVal) { this.getList(this.myDate); }, deep: true, }, markDateMore: { handler(val, oldVal) { this.getList(this.myDate); }, deep: true, }, agoDayHide: { handler(val, oldVal) { this.getList(this.myDate); }, deep: true, }, futureDayHide: { handler(val, oldVal) { this.getList(this.myDate); }, deep: true, }, sundayStart: { handler(val, oldVal) { this.intStart(); this.getList(this.myDate); }, deep: true, }, }, }; </script> <style scoped> @media screen and (min-width: 460px) { .wh_item_date:hover { background: #00baff; cursor: pointer; } } * { margin: 0; padding: 0; } .wh_container { max-width: 410px; margin: auto; } li { list-style-type: none; } .wh_top_changge { display: flex; } .wh_top_changge li { cursor: pointer; display: flex; color: #040b29; font-size: 18px; flex: 1; justify-content: center; align-items: center; height: 47px; } .wh_top_changge .wh_content_li { cursor: auto; flex: 2.5; } .wh_content_all { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", STHeiti, "Microsoft Yahei", Tahoma, Simsun, sans-serif; background-color: #ffffff; width: 100%; overflow: hidden; padding-bottom: 8px; border-radius: 10px; } .wh_content { display: flex; flex-wrap: wrap; padding: 0 3% 0 3%; width: 100%; justify-content: center; } .wh_content:first-child .wh_content_item_tag, .wh_content:first-child .wh_content_item { color: #ddd; font-size: 16px; } .wh_content_item, .wh_content_item_tag { font-size: 15px; width: 13.4%; text-align: center; color: #fff; position: relative; } .wh_content_item { height: 40px; } .wh_top_tag { width: 40px; height: 40px; line-height: 40px; margin: auto; display: flex; justify-content: center; align-items: center; color: #9b9da9; } .wh_item_date { width: 40px; height: 40px; line-height: 40px; margin: auto; display: flex; justify-content: center; align-items: center; color: #040b29; } .wh_jiantou1 { width: 12px; height: 12px; border-top: 2px solid #9b9da9; border-left: 2px solid #9b9da9; transform: rotate(-45deg); } .wh_jiantou1:active, .wh_jiantou2:active { border-color: #040b29; } .wh_jiantou2 { width: 12px; height: 12px; border-top: 2px solid #9b9da9; border-right: 2px solid #9b9da9; transform: rotate(45deg); } .wh_content_item > .wh_isMark { margin: auto; /* border-radius:10px; */ background:rgba(235, 246, 255, 1); z-index: 2; } .wh_content_item .wh_other_dayhide { color: #bfbfbf; } .wh_content_item .wh_want_dayhide { color: #9b9da9; } .wh_content_item .wh_isToday { /* background: #00BAFF; border-radius:10px; */ color: rgba(130, 183, 225, 1); } .wh_content_item .wh_pre_day { color: red; } .wh_content_item .wh_chose_day { background: rgba(168, 208, 240, 1); color: #fff; border-radius: 10px; } </style>
calendar.js 是生成月份盘,月数多少天的逻辑
import moment from "moment"; export default { // 当某月的天数 getDaysInOneMonth(date) { const year = date.getFullYear(); const month = date.getMonth() + 1; const d = new Date(year, month, 0); return d.getDate(); }, // 向前空几个 getMonthweek(date) { const year = date.getFullYear(); const month = date.getMonth() + 1; const dateFirstOne = new Date(year + '/' + month + '/1'); return this.sundayStart ? dateFirstOne.getDay() == 0 ? 7 : dateFirstOne.getDay() : dateFirstOne.getDay() == 0 ? 6 : dateFirstOne.getDay() - 1; }, /** * 获取当前日期上个月或者下个月 */ getOtherMonth(date, str = 'nextMonth') { const timeArray = this.dateFormat(date).split('/'); const year = timeArray[0]; const month = timeArray[1]; const day = timeArray[2]; let year2 = year; let month2; if (str === 'nextMonth') { month2 = parseInt(month) + 1; if (month2 == 13) { year2 = parseInt(year2) + 1; month2 = 1; } } else { month2 = parseInt(month) - 1; if (month2 == 0) { year2 = parseInt(year2) - 1; month2 = 12; } } let day2 = day; const days2 = new Date(year2, month2, 0).getDate(); if (day2 > days2) { day2 = days2; } if (month2 < 10) { month2 = '0' + month2; } if (day2 < 10) { day2 = '0' + day2; } const t2 = year2 + '/' + month2 + '/' + day2; return new Date(t2); }, // 上个月末尾的一些日期 getLeftArr(date) { const arr = []; const leftNum = this.getMonthweek(date); const num = this.getDaysInOneMonth(this.getOtherMonth(date, 'preMonth')) - leftNum + 1; const preDate = this.getOtherMonth(date, 'preMonth'); // 上个月多少开始 for (let i = 0; i < leftNum; i++) { const nowTime = preDate.getFullYear() + '/' + (preDate.getMonth() + 1) + '/' + (num + i); arr.push({ id: num + i, date: nowTime, isToday: false, isPreDay:false, otherMonth: 'preMonth', }); } return arr; }, // 下个月末尾的一些日期 getRightArr(date) { const arr = []; const nextDate = this.getOtherMonth(date, 'nextMonth'); const leftLength = this.getDaysInOneMonth(date) + this.getMonthweek(date); const _length = 7 - leftLength % 7; for (let i = 0; i < _length; i++) { const nowTime = nextDate.getFullYear() + '/' + (nextDate.getMonth() + 1) + '/' + (i + 1); arr.push({ id: i + 1, date: nowTime, isToday: false, isPreDay:false, otherMonth: 'nextMonth', }); } return arr; }, // format日期 dateFormat(date) { date = typeof date === 'string' ? new Date(date.replace(/-/g, '/')) : date; return date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate(); }, // 获取某月的列表不包括上月和下月 getMonthListNoOther(date) { const arr = []; const num = this.getDaysInOneMonth(date); const year = date.getFullYear(); const month = date.getMonth() + 1; const toDay = this.dateFormat(new Date()); console.log(toDay,'今日日期的格式化'); var curDate = new Date(); var preDate = Date.parse(new Date(curDate.getTime() - 24 * 60 * 60 * 1000)); //前一天 const preDay = this.dateFormat(moment(preDate).format('YYYY-MM-DD')); console.log(preDay,'前一日日期的格式化'); for (let i = 0; i < num; i++) { const nowTime = year + '/' + month + '/' + (i + 1); arr.push({ id: i + 1, date: nowTime, isToday: toDay === nowTime, isPreDay: false, otherMonth: 'nowMonth', }); } // console.log(arr,'月份日期') return arr; }, // 获取某月的列表 用于渲染 getMonthList(date) { return [ ...this.getLeftArr(date), ...this.getMonthListNoOther(date), ...this.getRightArr(date) ]; }, // 默认是周一开始 sundayStart: false, };
组件的导出
// index.js import CalendarDemo from './calendar.vue'; export default CalendarDemo;
组件的使用
<template> <div style="background-color:#F7F7F7;padding:0.43rem"> <!-- <NewAppHeader title="行驶里程数据" :backGroundTrans="true" :hideGoback="true"> --> <NewAppHeader :title="DATA_FOREZEN.titleName[type]" :backGroundTrans="true" :hideGoback="true"> <span class="d_left" @click="back"></span> <span class="d_right" @click="showModal('demo')"></span> </NewAppHeader> <div class="d_main" style="padding-top:1rem"> <div class="v_tab"> <div class="tab_general" :class="tab == 1 ? 'tab_active' : ''" @click="changeTab(1)"> 日 </div> <div class="tab_general" :class="tab == 2 ? 'tab_active' : ''" @click="changeTab(2)"> 周 </div> </div> </div> <div style="margin-top:0.45rem;"> <div v-if="tab === 1"> <CalendarDemo ref="Calendar" @change="handelChange" v-on:changeMonth="changeDate" :defaultDate="defaultDate" :futureDayHide="disableDay" :sundayStart="sundayStart" :textTop="textTop" ></CalendarDemo> </div> <div v-else> <CalendarDemo ref="Calendar" v-on:choseDay="clickDay" v-on:changeMonth="changeDate" :defaultDate="defaultDate" :futureDayHide="disableDay" :markDate="markDate" :rangeDate="rangeDate" :sundayStart="sundayStart" :textTop="textTop" ></CalendarDemo> </div> </div> </div> </template> <script> import "@/utils/flexible.js"; const NewAppHeader = () => import("@/components/NewAppHeader"); import CalendarDemo from "./compnent/index"; import moment from "moment"; const DATA_FOREZEN = { titleName:{ voice:'语音控制数据', switch:'远程车控数据', distance:'行驶里程数据' }, noDataTip:{ voice:'无语音控制数据', switch:'无远程车控数据', distance:'无行驶里程数据' }, totoalTip:{ voice:'累计控制', switch:'累计使用远程车控', distance:'累计行驶' }, weekTotal:{ voice:'累计语音控制', switch:'远程车控数据', distance:'累计行驶里程' }, noteC:{ voice:'每一段语音数据都有一段故事', switch:'新宝骏车控大玩家邀你来挑战', distance:'每一段行驶里程都有一段故事' }, Company:{ voice:'次', distance:'KM', switch:'次' }, dateType:{ 1:'周', 2:'周' }, shareType:{ 1:'今日', 2:'本周' } } export default { data() { return { DATA_FOREZEN, sundayStart: true, textTop: ["日", "一", "二", "三", "四", "五", "六"], isWeek: true, tab: 1, defaultDate: Date.parse(new Date()), disableDay: "", markDate: [], rangeDate: [], weekList: [ { date: "1", num: "1" }, { date: "2", num: "2" }, { date: "3", num: "3" }, { date: "4", num: "4" }, { date: "5", num: "5" }, { date: "6", num: "6" }, { date: "7", num: "7" } ], //周里程的列表 lastList: [], }; }, components: { CalendarDemo, NewAppHeader }, filters: { filterDate(value) { return moment(value).format("MM月DD日"); } }, watch: { tab: { handler(val, oldVal) { console.log(val, oldVal); if (val == 2) { this.markDate = this.weekDay(); this.rangeDate = this.weekDay(); this.getData(); } }, deep: true } }, created() { // 时间今日之前的时间不可选 let today = moment().format("YYYY-MM-DD"); this.disableDay = (moment(today).valueOf() / 1000).toString(); // 处理前默认前一天的逻辑 var curDate = new Date(); var preDate = Date.parse(new Date(curDate.getTime() - 24 * 60 * 60 * 1000)); //前一天 this.defaultDate = new Date(preDate); this.dateStr = moment(this.defaultDate).format("MM月DD日"); // 获取行驶数据 this.getData(); }, methods: { back() { this.$router.go(-1); }, // 切换日月 changeTab(arg) { this.tab = arg; this.getData(); }, weekDay(data) { if (data) { this.oToday = new Date(data); } else { this.oToday = new Date(); } let defaultDay = 2; console.log(data,'data') this.currentDay = this.oToday.getDay(); // 获取当前周几 console.log(this.currentDay,'currentDay ') if (this.currentDay == 0) { this.currentDay = 7; } let distansDay = this.currentDay - defaultDay; let mondayTime = this.oToday.getTime() - distansDay * 24 * 60 * 60 * 1000; let sundayTime = this.oToday.getTime() + (6 - this.currentDay) * 24 * 60 * 60 * 1000; let arr = []; for (let i = 0; i < 7; i++) { arr.push( moment(mondayTime) .add("days", i) .format("YYYY-MM-DD") ); } console.log(arr) return arr; }, // 子组件的返回参数 clickDay(data) { console.log(data, "时间"); if (this.tab == 2) { this.rangeDate = this.weekDay(data); this.getData(); } else { this.defaultDate = data; this.dateStr = moment(data).format("MM月DD日"); this.getData(); } }, // 接口数据请求 getData() { // ... 省略啦 }, changeDate(data) { console.log(data); //左右点击切换月份 }, } }; </script> <style lang="less" scoped> /deep/ .mint-header-title { font-size: 0.48rem; color: #040b29; background-color: rgb(247, 247, 247); } // /deep/ .new-mt-header.trans{ // background-color: rgb(247, 247, 247); // } .d_left { position: fixed; padding: 0.25rem; top: 0.25rem; background-size: contain; background-repeat: no-repeat; background-position: center; left: 0.43rem; height: 0.44rem; width: 0.25rem; display: inline-block; background-image: url("./../../imgs/vInternet/d_back.png"); } .d_right { height: 0.5rem; width: 0.5rem; background-image: url("./../../imgs/vInternet/d_share.png"); display: inline-block; background-repeat: no-repeat; margin-right: 0.2rem; margin-top: 0.35rem; background-size: 100%; } .d_main { display: flex; justify-content: center; align-items: center; .v_tab { height: 0.93rem; width: 3.73rem; border-radius: 0.53rem; color: #040b29; background-color: #ffffff; display: inherit; align-items: center; justify-content: center; font-size: 0.43rem; .tab_general { width: 1.87rem; border-radius: 0.53rem; height: 0.93rem; line-height: 0.93rem; text-align: center; } .tab_active { background: rgba(235, 246, 255, 1); } } } .d_note { height: 0.59rem; font-size: 0.51rem; font-family: Helvetica; color: rgba(4, 11, 41, 1); line-height: 0.59rem; margin: 0.41rem 0rem; font-style: italic; font-weight: 600; } } </style>
加载全部内容