vue的h5日历组件实现详解
短信预约 -IT技能 免费直播动态提醒
本文实例为大家分享了vue的h5日历组件实现代码,供大家参考,具体内容如下
日历样式自定义
日历组件
<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;
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 {
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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341