本文目标:
在vue2场景下,实现el-date-picker组件的,type为datetimerange时,限制时分秒的功能。
我的场景是,希望,当开始日期和结束日期一致时,选择了开始时间,再去选择结束时间时,这个结束时间选择器里,早于开始时间的都置灰,鼠标经过有禁用的效果
网上搜了很多文章都是type=datetime
的场景,不符合我的需求
核心思路:因为该选择器,针对type为datetimerange时,没有直接去限制时分秒的api写在官方文档中,所以,我的做法是结合dom操作和点击事件来实现。
1. 第一步:拿dom,绑定事件
在点击时间选择框的一刹那,去拿我们需要的dom容器,在时间选择器的focus事件时触发
diff
<el-date-picker
v-model="searchcond.searchPeriod"
type="datetimerange"
:range-separator="$t('log.to')"
:start-placeholder="$t('log.startTime')"
:end-placeholder="$t('log.endTime')"
:picker-options="pickerOptions"
@change="validateDate"
+ @focus="getPickerDom"
@blur="deletePickerDom"
ref="datetime"
>
在getPickerDom
函数里面,我们去拿对应的dom
js
getPickerDom () {
this.$nextTick(() => {
// 开始日期的input
this.startDate = document.querySelector('.el-picker-panel .el-date-range-picker__editors-wrap:first-of-type .el-date-range-picker__time-picker-wrap:first-of-type .el-input__inner')
// 开始时间的input
this.startTime = document.querySelector('.el-picker-panel .el-date-range-picker__editors-wrap:first-of-type .el-date-range-picker__time-picker-wrap:last-of-type .el-input__inner')
// 确定按钮的button
this.sureBtn = document.querySelector('.el-picker-panel .el-date-range-picker__editors-wrap:first-of-type .el-date-range-picker__time-picker-wrap:last-of-type .el-time-panel__btn.confirm')
// 结束日期的input
this.endDate = document.querySelector('.el-picker-panel .el-date-range-picker__editors-wrap:last-of-type .el-date-range-picker__time-picker-wrap:first-of-type .el-input__inner')
// 日期选择器输入框输入内容失去焦点触发
this.startDate.addEventListener('blur', this.formatTimeDisable)
this.startTime.addEventListener('blur', this.formatTimeDisable)
// 时间选择器输入框点击确定的时候触发
this.sureBtn.addEventListener('click', this.formatTimeDisable)
})
},
对应的startDate startTime sureBtn endDate
请在data里面自己声明好鸭~
- 开始日期是这个input
-
开始时间是这个input
-
结束日期是这个input
-
确定按钮是这个btn
-
给startDate endDate sureBtn绑定blur事件的原因?我理解过来是,当选择了开始日期和结束日期,和开始时间这个三个input,以及点击了这个btn按钮的时候,执行该函数,更新操作。
2. 第二步:事件处理的逻辑
formatTimeDisable函数
内部要做什么操作?
js
formatTimeDisable () {
try {
const picker = this.$refs.datetime?.picker
// 拿到结束时间的"选择器"
const { maxTimePicker } = picker.$refs
// 判断,只有在开始日期和结束日期相等时,才去限制时分秒
if (this.startDate.value === this.endDate.value) {
// arr必须是二维数组,意味着"selectableRange"限制的时间范围可以有多个
let arr = [
[new Date(`${this.startDate.value} ${this.startTime.value}`), new Date(`${this.startDate.value} ${this.endTimeFormat}`)]
]
maxTimePicker.selectableRange = arr
// 这样限制的时分秒,时和分会有禁用的效果,但是秒没有禁用置灰的效果,但是也无法点击了,也不会影响开始时间
} else {
// 开始时间和结束时间不相等,不限制时分秒
maxTimePicker.selectableRange = []
}
} catch (error) {
console.log(error, 'error');
}
},
const picker = this.$refs.datetime?.picker
- this.$refs.datetime拿到的是这个
- this.$refs.datetime?.picker拿到的是这个,是我们要操作的
- const { maxTimePicker } = picker.$refs
picker.$refs里面有三个,
maxTimePicker里面是结束时间的选择器,我们要给这个里面的选择器进行禁用
- if (this.startDate.value === this.endDate.value) 拿到开始和结束的日期,比较是不是同一天,如果不是同一天,不需要对结束日期做出校验,走else maxTimePicker.selectableRange = [] selectableRange里面是一个二维数组,这个用来表示可以选择的日期范围,你看这里的显示的表示4.19日我可以选择从11:12:00到23:59:59的时间
- 当开始日期和结束日期是同一天,我们就是修改selectableRange的日期
- arr是二维数组,不然就会报错
- 注意,startDate startTime startDate都是我们之前拿得到的值,从input表单.value直接拿到(这是dom的语法啦)
- endTimeFormat是在data里面定义的,是一个默认值,我是这样写的
endTimeFormat: '23:59:59'
maxTimePicker.selectableRange = arr
这样去进行赋值
js
// arr必须是二维数组,意味着"selectableRange"限制的时间范围可以有多个
let arr = [
[new Date(`${this.startDate.value} ${this.startTime.value}`), new Date(`${this.startDate.value} ${this.endTimeFormat}`)]
]
- 在失去焦点的时候,去清空这些事件,防止内存泄漏
js
this.startTime.removeEventListener('blur', this.formatTimeDisable)
this.startDate.removeEventListener('blur', this.formatTimeDisable)
this.sureBtn.removeEventListener('click', this.formatTimeDisable)
this.startDate = null
this.startTime = null
this.sureBtn = null
this.endDate = null
- 只是美中不足的是,在秒这里没能限制好
原因在于,element-ui里面针对time-spinner组件,没有给秒增加disabled属性 时和分都有
唯独秒没有