vue平铺日历组件之按住ctrl、shift键实现跨月、跨年多选日期的功能
已经好久没有更新过博客了,大概有两三年了吧,因为换了工作,工作也比较忙,所以也就没有时间来写技术博客,期间也一直想写,但自己又比较懒,就给耽误了。今天这篇先续上,下一篇什么时候写,我也不知道,随心所欲、随遇而安、安之若素、素不相识也就无所谓了吧。
一开始看到这个功能需求,我也很懵逼,因为从来没有做过啊,哈哈。。。但转念一想既然产品能提出这个需求,想必会有人实现过,就去网上查了查资料,果不其然,还真有人做过,但离我想要的效果还是差着十万八千里,所以按照网上大神的思路,结合我司的实际需求,自己就把它给捣鼓出来了。
其实刚做好的效果还是能实现产品的需求的,我就让同事帮忙测试一下看看有没有什么bug,因为我司对bug的要求以及对用户体验的要求还是很严格的,所以在同事的实际测试以及提醒下,后面我又参照电脑上基于ctrl、shift键来选中文件的实际效果做了改进,算是不给测试提bug的机会吧。
照旧先上两张最后实现的效果图:
先来看看实现单月的日期组件calendar.vue
{{monthCN[month]}}月
- {{item}}
-
{{item.day}}
{{item.day}}
从以上也能看出,我们的需求还是很复杂的,比如,历史日期也就是所谓的过期的日期不能被选中,周六周日的日期要标红,还可以把工作日置为休息日,休息日置为工作日等等。这些功能说起来就一句话,可要实现出来,那可就属实太复杂了。
对了,在实现的过程中,我还使用到了vuex来保存点击选中的数据calendar.js:
let selectList = []
let shiftData = null
let shiftDate = ''
let currentSelect = []
let lastSelect = []
// 获取两个日期中间的所有日期
const getBetweenDay = (starDay, endDay) => {
var arr = []
var dates = []
// 设置两个日期UTC时间
var db = new Date(starDay)
var de = new Date(endDay)
// 获取两个日期GTM时间
var s = db.getTime() - 24 * 60 * 60 * 1000
var d = de.getTime() - 24 * 60 * 60 * 1000
// 获取到两个日期之间的每一天的毫秒数
for (var i = s; i = 10 ? (time.getMonth() + 1) : ('0' + (time.getMonth() + 1))
var day = time.getDate() >= 10 ? time.getDate() : ('0' + time.getDate())
var YYMMDD = year + '' + mouth + '' + day
dates.push(YYMMDD)
}
return dates
}
const shiftSelect = (dateStr, item) => {
if (!shiftData) {
shiftData = item.date
shiftDate = ${item.year}-${item.month}-${item.day}
// 如果当前日期已选中,再次点击当前日期就取消选中。
if (selectList.includes(dateStr)) {
selectList.splice(selectList.indexOf(dateStr), 1)
} else {
selectList.push(dateStr)
}
} else {
if (shiftData item.date) {
currentSelect = getBetweenDay(${item.year}-${item.month}-${item.day}
, shiftDate)
} else {
currentSelect = [dateStr]
}
selectList = selectList.filter(item => !lastSelect.includes(item)) // 移除上次按shift复制的
selectList = selectList.concat(currentSelect) // 添加本次按shift复制的
lastSelect = currentSelect
}
}
export default {
namespaced: true,
state: {
selectList: []
},
mutations: {
setSelectCalendar (s, { dateStr, item, isCtrl, isShift }) {
// 按住ctrl
if (isCtrl && !isShift) {
// 如果当前日期已选中,再次点击当前日期就取消选中。
if (selectList.includes(dateStr)) {
selectList.splice(selectList.indexOf(dateStr), 1)
} else {
selectList.push(dateStr)
}
// 加上lastSelect = []这个就会在shift连续选了多个后,再按住ctrl键取消已选中的日期的中间的几个后,下次再按住
// shift多选时,就会从按住ctrl取消选中的最后一个日期开始连续选择,但刚才取消已选中的那些日期
// 之前的已经选中的日期依旧处于选中状态,与电脑自身的按住shift键多选的效果略有不同,所以要注释掉这串代码。
// lastSelect = [] // 最开始这串代码是放开的
} else if (isShift && !isCtrl) {
// 加上selectList = []可以实现按住ctrl单选几个不连续的日期后,再按住shift键连选其他日期,就可以把之前
// 按住ctrl键单选的其他日期都取消选中。不加selectList = []是可以在按住shift键连选其他日期时同时保留之前
// 按住ctrl键单选的其他日期。
selectList = [] // 最开始这串代码是没有的
shiftSelect(dateStr, item)
} else if (isCtrl && isShift) { // 同时按住ctrl和shift
lastSelect = []
shiftSelect(dateStr, item)
} else { // 不按ctrl和shift,一次只能选择一个
selectList = [dateStr]
}
if (!isShift) {
shiftData = item.date
shiftDate = ${item.year}-${item.month}-${item.day}
}
selectList = [...new Set(selectList)].sort() // 去重、排序
s.selectList = selectList
},
setSelectEmpty (s) {
selectList = []
shiftData = null
shiftDate = ''
currentSelect = []
lastSelect = []
s.selectList = []
}
}
}
再来看看在以上单个日期组件的基础上实现1年12个月日历平铺的代码吧:
写到这里就不准备再往下写了,所有的代码都贴出来了。如果你想要的效果跟我的这个不太一样,你自己在这个基础上改吧改吧应该就可以用了。其实最关键的部分也就是那个按住ctrl、shift键实现跨月、跨年多选日期,理解了这个原理,其余的实现部分尽管复杂但并不难。
作者:小坏
出处:http://tnnyang.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
THE END
二维码