template:div id=calendar_content class=calendar_content @touchstart=handleStart @touchmove=handleMove @touchend=handleEnddiv id=calendar_content_wrapper_prev class=calendar_content_wr...
template:
<div id="calendar_content" class="calendar_content" @touchstart="handleStart" @touchmove="handleMove" @touchend="handleEnd">
<div id="calendar_content_wrapper_prev" class="calendar_content_wrapper prev">
<div class="week_wrap" v-for="(week, index) in prevDaysArr" :key="index">
<div class="day_wrap" v-for="(day, indexDay) in week" :key="indexDay" :class="[6, 7].includes(day.week) ? 'rest_day' : ''">
<div @click="changeActiveDay(day)">
<p class="day_text" :class="activeDay === day.timeStr ? 'active_day' : ''">{{day.timeStr ? new Date(day.timeStr).getDate() : ''}}</p>
</div>
<template v-if="day.id">
<span v-if="day.status == 0" class="normalCircle"></span>
<span v-else class="abnormalCircle"></span>
</template>
</div>
</div>
</div>
<div id="calendar_content_wrapper" class="calendar_content_wrapper middle">
<div class="week_wrap" v-for="(week, index) in daysArr" :key="index">
<div class="day_wrap" v-for="(day, indexDay) in week" :key="indexDay" :class="[6, 7].includes(day.week) ? 'rest_day' : ''">
<div @click="changeActiveDay(day)">
<p class="day_text" :class="activeDay === day.timeStr ? 'active_day' : ''">{{day.timeStr ? new Date(day.timeStr).getDate() : ''}}</p>
</div>
<template v-if="day.id">
<span v-if="day.status == 0" class="normalCircle"></span>
<span v-else class="abnormalCircle"></span>
</template>
</div>
</div>
</div>
<div id="calendar_content_wrapper_next" class="calendar_content_wrapper next">
<div class="week_wrap" v-for="(week, index) in nextDaysArr" :key="index">
<div class="day_wrap" v-for="(day, indexDay) in week" :key="indexDay" :class="[6, 7].includes(day.week) ? 'rest_day' : ''">
<div @click="changeActiveDay(day)">
<p class="day_text" :class="activeDay === day.timeStr ? 'active_day' : ''">{{day.timeStr ? new Date(day.timeStr).getDate() : ''}}</p>
</div>
<template v-if="day.id">
<span v-if="day.status == 0" class="normalCircle"></span>
<span v-else class="abnormalCircle"></span>
</template>
</div>
</div>
</div>
</div>
data:
nowDay: '',
nowWeekDay: '',
prevDaysArr: [],
daysArr: [],
nextDaysArr: [],
activeDay: '',
activeDayInfo: {},// 坐标
startClientX: '',
isReset: false,
methods:
// 组装查询月份的数组
assembleDayArr (key, date) {
let allDays = this.getMonthDay(date || this.nowDay);
// 查询每周一的下标
let indexArr = [];
allDays.map((val, index) => {
if(val.week === 1){
indexArr.push(index);
}
});
// 如果第一天正好是 周一 则剔除indexArr[0]
if(indexArr[0] === 0){
indexArr.splice(0, 1);
};
// 查询有几周
let weeks = indexArr.length + 1;
// 将 每周塞进数组
let arr = [];
for(let i = 0;i < weeks;i++){
if(i === 0){
arr[i] = allDays.slice(0, indexArr[0]);
}else{
arr[i] = allDays.slice(indexArr[i-1], indexArr[i]);
}
if(arr[i].length < 7 && arr[i][0].week === 1){
let diff = 7 - arr[i].length;
for(let j = 0;j < diff;j++){
arr[i].push({});
}
}else if(arr[i].length < 7 && arr[i][0].week !== 1){
let diff = 7 - arr[i].length;
for(let j = 0;j < diff;j++){
arr[i].unshift({});
}
}
};
this[key] = arr;
},
// 选中日期改变事件
changeActiveDay (day) {
if(day.timeStr && day.timeStr !== this.activeDayInfo.timeStr){
this.activeDay = day.timeStr;
this.activeDayInfo = {...day};
this.nowDay = day.timeStr;
this.nowWeekDay = this.findNowWeek();
}
},
// 头部时间修改
changeMonth (flag, key) {
let resultMonth;
let nowChooseMonth = new Date(this.nowDay).getMonth();
if(flag === 'reduce'){
resultMonth = new Date(this.nowDay).setMonth(nowChooseMonth - 1, 1);
}else {
resultMonth = new Date(this.nowDay).setMonth(nowChooseMonth + 1, 1);
if(resultMonth > new Date().getTime()){
this.$toast.fail('不能选择未来月份');
return;
};
};
// 设置头部显示日期 查看是否是当前月份
if(dateFormat(new Date(), 'yyyy-MM') === dateFormat(new Date(resultMonth), 'yyyy-MM')){
this.nowDay = dateFormat(new Date(), 'yyyy-MM-dd');
}else{
this.nowDay = dateFormat(new Date(resultMonth), 'yyyy-MM-01');
};
this.activeDay = this.nowDay;
this.nowWeekDay = this.findNowWeek();
this.assembleDayArr(key || 'daysArr');
this.getList();
},
// 滑动开始
handleStart (e) {
this.startClientX = e.changedTouches[0].clientX;
},
// 滑动中
handleMove (e) {
e.preventDefault();
// isReset 防止过多次 计算前后数组;
if(!this.isReset && Math.abs(e.changedTouches[0].clientX - this.startClientX) > 1){
let nowChooseMonth = new Date(this.nowDay).getMonth();
let prevMonth = new Date(this.nowDay).setMonth(nowChooseMonth - 1);
let nextMonth = new Date(this.nowDay).setMonth(nowChooseMonth + 1);
this.assembleDayArr('prevDaysArr', dateFormat(new Date(prevMonth), 'yyyy-MM-dd'));
this.assembleDayArr('nextDaysArr', dateFormat(new Date(nextMonth), 'yyyy-MM-dd'));
this.isReset = true;
}
let dom = document.getElementById('calendar_content');
dom.style.marginLeft = (e.changedTouches[0].clientX - this.startClientX) + 'px';
},
// 滑动结束
handleEnd (e) {
let diffX = e.changedTouches[0].clientX - this.startClientX;
let dom = document.getElementById('calendar_content');
if(Math.abs(diffX) === 0){
return;
}
if(Math.abs(diffX) > 100){
if(diffX < 0){
let nowChooseMonth = new Date(this.nowDay).getMonth();
let resultMonth = new Date(this.nowDay).setMonth(nowChooseMonth + 1);
if(resultMonth > new Date().getTime()){
goBack(dom, diffX);
this.$toast.fail('不能选择未来月份');
return;
};
}
let animation = document.getElementById("calendar_content").animate([
{ marginLeft: `${diffX}px`},
{ marginLeft: diffX > 0 ? '7.5rem' : '-7.5rem'}
], {
duration: 500,
delay: 0
});
animation.play();
setTimeout(() => {
dom.style.marginLeft = 0;
if(diffX > 0){
this.changeMonth('reduce', 'daysArr');
};
if(diffX < 0){
this.changeMonth('plus', 'daysArr');
};
this.isReset = false;
}, 501);
}else{
goBack(dom, diffX);
};
// 回到远点 手指移动距离不超过100 以及 不能选择未来月份情况
function goBack (rDom, reference) {
let animation = document.getElementById("calendar_content").animate([
{ marginLeft: `${reference}px`},
{ marginLeft: 0}
], {
duration: 500,
delay: 0
});
animation.play();
setTimeout(() => {
rDom.style.marginLeft = 0;
}, 501)
}
},
// 返回文字 星期几
findNowWeek () {
let nowWeek = new Date(this.nowDay).getDay();
let weekInfo = {
0: '星期日',
1: '星期一',
2: '星期二',
3: '星期三',
4: '星期四',
5: '星期五',
6: '星期六',
};
return weekInfo[nowWeek];
},
// 获取 月份 对应的所有日期
getMonthDay (date) {
let now = new Date(date);
let current_month_num = this.mGetDate(date);
let current_month = [];
for (let i = 1; i <= current_month_num; i++) {
let day = now.setDate(i);
let everyDay = dateFormat(new Date(day), 'yyyy-MM-dd');
current_month.push({
timeStr: everyDay,
week: new Date(everyDay).getDay() === 0 ? 7 :new Date(everyDay).getDay(),
foreInfo: {},
afterInfo: {},
});
};
return current_month;
},
// 获取当前月的天数
mGetDate (date) {
var date = new Date(date);
var year = date.getFullYear();
var month = date.getMonth() + 1;
var d = new Date(year, month, 0);
return d.getDate();
},
css:
.calendar_content{
position: relative;
width: 22.5rem;
// top: .6rem;
left: -7.5rem;
display: flex;
.calendar_content_wrapper{
flex: 1;
&.prev{
left: 0;
}
&.middle{
left: 7.5rem;
}
&.next{
right: 0;
}
}
}
.week_wrap{
display: flex;
.day_wrap{
flex: 1;
&.rest_day{
color: #BABABA;
}
p{
margin: .1rem auto;
&.day_text{
width: .54rem;
height: .54rem;
line-height: .54rem;
border-radius: 100%;
}
&.active_day{
background: #3f6ad3;
color: white;
}
}
}
}
沃梦达教程
本文标题为:基于vue手写仿钉钉 滑动日历
猜你喜欢
- layui数据表格以及传数据方式 2022-12-13
- 关于 html:如何从 css 表中删除边距和填充 2022-09-21
- jsPlumb+vue创建字段映射关系 2023-10-08
- 深入浅析AjaxFileUpload实现单个文件的 Ajax 文件上传库 2022-12-15
- 1 Vue - 简介 2023-10-08
- vue keep-alive 2023-10-08
- JS实现左侧菜单工具栏 2022-08-31
- 基于CORS实现WebApi Ajax 跨域请求解决方法 2023-02-14
- ajax实现输入提示效果 2023-02-14
- javascript 判断当前浏览器版本并判断ie版本 2023-08-08
