解决uni-datetime-picker不可选择时间长度的问题

1,616 阅读2分钟

背景

uni-datetime-picker支持限制选择时间开始和结束,但不支持限制选择时间范围长度,比如最多可选择一个月,碰到一个需求需要默认可以任意选择,在选择一个日期后最多选择一个月内的日期,因项目是本人自己独立完成,看了看uni-datetime-picker组件源码的逻辑比较清晰、易修改,所以选择直接改源码,并在项目内记录了修改原因和方式

代码分析

uni-datetime-picker组件依赖的calendar组件里面有一个插入模式insertuni-datetime-picker组件里通过判断isPhone时会给insert赋值为false,而在calendar组件里日期变化会触发的change方法中会判断如果不是插入模式就不会派发事件,而在uni-datetime-picker组件里手机端也没有监听change事件

一句话概括就是:只选择一个日期后没有触发回调,来控制修改开始/结束时间

解决步骤

1. calendar组件里面的choiceDate日期改变事件中触发的change事件,让此事件派发事件
choiceDate(weeks) {
    // ……
    this.tempRange.before = this.cale.multipleStatus.before
    this.tempRange.after = this.cale.multipleStatus.after
    // this.change()
    // 改为
    this.change(1)
}

change(e) {
    // if (!this.insert) return 
    // 改为
    if (!this.insert && e !== 1) return
    this.setEmit('change')
}
2. uni-datetime-picker组件监听对应子组件事件,继续向上派发事件
// 第一步 监听子组件事件
<calendar v-show="isPhone" ref="mobile" :clearDate="false" :date="defSingleDate" :defTime="reactMobDefTime"
    :start-date="caleRange.startDate" :end-date="caleRange.endDate" :selectableTimes="mobSelectableTime"
    :pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :typeHasTime="hasTime" :insert="false"
    :hideSecond="hideSecond" @confirm="mobileChange"
/>
// 改为(只添加监听change事件)
<calendar v-show="isPhone" ref="mobile" :clearDate="false" :date="defSingleDate" :defTime="reactMobDefTime"
    :start-date="caleRange.startDate" :end-date="caleRange.endDate" :selectableTimes="mobSelectableTime"
    :pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :typeHasTime="hasTime" :insert="false"
    :hideSecond="hideSecond" @confirm="mobileChange" @change="myChange" 
/>
// 第二步 将接受到的数据直接向上派发事件
myChange (e) {
    // console.log(e, 'e')
    this.$emit('myChange', e)
}
3. 在自己的组件中监听myChange事件,控制uni-datetime-picker组件startend
<uni-datetime-picker v-model="dateRange" type="daterange" @change="dateRangeChange" @myChange="myChange" :start="dateStart" :end="dateEnd">
​
myChange (e) {
    // 判断如果是只选择了一个日期
    if (e.range.before && !e.range.after) {
        // 当前选择的日期
        // 此处使用dayjs进行操作,也可直接将 e.range.before 转换为时间戳,然后再计算对应的毫秒数进行复制,uni-datetime-picker组件 直接接收时间戳
        const chooseDate = dayjs(e.range.before)
        this.dateStart = chooseDate.add(1, 'month').format('YYYY-MM-DD')
        this.dateEnd = chooseDate.subtract(1, 'month').format('YYYY-MM-DD')
    }
}

欢迎进行讨论