el-date-picker日期范围不能跨disabledDate选择

日历控件是我见过做复杂的组件了,当然除了富文本之外。很多日历组件在实现可选日期的时候都是大同小异的,要么提供一个enablexxx要么提供一个disabledxxx的函数,让使用者明确告诉它哪些日期是可用的。element中的日历控件也提供了这样一个属性disabledDate,它接收一个日期参数,返回true表示不可选择,否则是可以选择。

我们一般的处理方法是调用一个接口,后端告诉我们哪些是可选的哪些是不可选的,这样我们在disabledDate中通过查询日期是否在可选/不可选的列表中来返回。粗略看起来这个逻辑没问题,但是当遇到日期范围时问题就没那么简单了。日历首次弹开,不能选中的日期都是disabled的,这个没问题。不过当我们选择了一个开始日期,那么结束日期是不是要控制一下呢?如果不控制,势必会产生出一个日期范围,其中包含了一些不可用的日期。这个是不允许的。这也是我这篇文章要说明的问题。

先说思路,el-date-picker有一个onPick的事件回调,对于日期范围组件,点击开始日期和结束日期都会触发这个事件。我会在这里来区分出点击开始日期,然后置一个标志位,供后面使用,比如就叫firstDateClicked吧。

onPick({minDate, maxDate}) {
	if (minDate && !maxDate) {
		this.firstDateClicked = true;
	} else {
		this.firstDateClicked = false;
	}
}

这里置true是足够了,但是关于什么时候置为false还需要再进一步讨论。如果我正常操作即点击了开始和结束日期,选择了一个日期范围,那这个代码没问题,如果我点击完开始日期后,中途点击了别的地方,导致日期控件消失了,此时也要把firstDateClicked置位false的。所以我觉得把置位false的逻辑放到日期控件消失时最理想。找遍了日期控件的文档也没能找到,我最后用了日期控件的blur事件。所以上面的代码就变成了

...
<el-date-picker @blur="firstDateClicked = false" ....
...
onPick({minDate, maxDate}) {
	if (minDate && !maxDate) {
		this.firstDateClicked = true;
	}
}

好了,下面来说一下关键的部分了——disabledDate函数。说一下思路,在firstDateClicked为false时,我们按照以往的逻辑就行。当firstDateClicked为true时,我们要把跟第一个日期相连的所有可用日期保持可用,别的都应是不可用的。我这里假设我们有一个不可用日期范围的数组,如下,这个数组是按时间从小到大排序的。

disabledDates: [{
	beginDate: '',
	endDate: ''
}]

那么我们的disabledDate回调应该如下:

disabledDate: (date) => {
	if (!this.firstDateClicked) {
		return this.findInDisabledDates(date); // findInDisabledDates这个函数就是在disabledDates中找有没有date,很简单,就不列出了
	} else {
		// 找到date左边不可用的范围
		const letfDisabledDate = this.findLeftDisabledDate(date);
		// 找到date右边不可用的范围
		const rightDisabledDate = this.findRightDisabledDate(date);
		// 如果只有左边界
		if (leftDisabledDate && !rightDisabledDate) {
			const time = new Date(leftDisabledDate.endDate).getTime();
			  if (date.getTime() <= time) {
					return true;
			  }
		} else if (!leftDisabled && rightDisabledDate) {		// 如果只有右边界
			const time = new Date(rightDisabledDate.startDate).getTime();
			if (date.getTime() >= time) {
				return true;
			}
		} else if (leftDisabled && rightDisabledDate) {		// 两个边界都有
			const leftTime = (new Date(leftDisabledDate.endDate)).getTime();
			const rightTime = (new Date(rightDisabledDate.startdate)).getTime();
			const time = date.getTime();
			if (time <= leftTime || time >= rightTime) {
				return true;
			}
		} else {	// 两个边界都没有
			return false;
		}
	}
},

...

...

,
findLeftDisabledDate: (date) => {
	const reversedDisabledDates = (JSON.parse(JSON.stringify(this.disabledDates)).reverse();
	const time = date.getTime();
	return reversedDisabledDates.find(item => {
		const t= (new Date(item.endDate)).getTime();
		return t < time;
	});
},
findRightDisabledDate: (date) => {
	const time = date.getTime();
	return this.disabledDates.find(item => {
		const t= (new Date(item.startDate)).getTime();
		return t > time;
	});
}

以上是手敲的(公司代码拷贝不出来),可能运行不起来,但是思路是正确的,亲测可用

如果有帮助,请点赞:)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值