Debug-039-el-date-picker组件手动输入时间日期的问题处理

发布于:2025-08-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

图1-外输入框

图2-内输入框

图3

     

问题描述:

        这两天在迭代功能的时候,基本上碰到的问题都是出自这个“时间日期选择框”,昨天的bug38也是解决这个组件。如上图1和2所示,可以把图1中的输入框叫外输入框,图2中的输入框叫内输入框,el-date-picker组件在官网上其实是有一个属性叫“editable”,可以禁止用户在文本框输入,但是很遗憾这个只能在外输入框生效,内输入框还是能编辑。由于业务上对日期有一些限制,因此不能选择任意日期,如果在内输入框手动输入日期,就限制不了日期范围,因此还是考虑禁用。
        以前其实碰到测试在外输入框输入日期的情况,然后使用editable属性可以规避用户输入,其实也不是不想让用户输入,只是有两个方面考虑:(1)效率不高,很少有人去手动输入(2)同时输入的格式不正确,导致不能转换成前后端约定的格式,然后查询报错,因此直接使用editable禁用外输入框。其实对于所有只有外框的el-date-picker组件已经可以说是规避解决了这个问题。但是对于type="datetimerange"的这种类型比较特殊的时间日期范围搜索框来说就不行,因为它有“内输入框”。其实还是很建议官方单独给datetimerange类型的搜索框加个属性,就是把内框也禁用掉,这样就能让我们这些牛马轻松点了。所以,这次的问题就是:我希望禁用掉内输入框输入。

方案:

        还是跟上次一样有问题先请教cursor的意见。这次的cursor没有帮我“一步到位”的解决问题,尽管它“天花乱坠”的说了很多,而且引导了它几次都还是没有成功,我就知道那接下来只能靠我自己了。不过它还是为我提供了思路:那就是通过给内输入框添加“readonly”属性的方式实现禁用。

        说到底,内输入框本质上也是个input,只要给它添加readonly或者把它disabled就可以达到我们的要求了。在没有相关的属性或者API能完成任务的时候,通过在合适的时机,使用原始的js插入属性的方式。

        添加 @focus="timeEditable"方法,当用户点击外框然后显示了日期面板的时候,使用nextTick确保此时内输入框渲染完毕之后,再利用js定位到内输入框的元素位置,然后给所有的input追加一个readonly属性即可实现禁止输入的效果。

        <el-date-picker
          v-else-if="item.type === 'DATEPICKER'"
          :key="item?.dateType + (item?.valueFormat || '')"
          v-model="form[item.key]"
          :type="item.dateType ?? 'daterange'"
          :style="{ width: item.dateType ? '400px' : '300px' }"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          range-separator="至"
          :clearable="!!item.clearable"
          :editable="false"
          :disabled-date="(time: Date) => item.dynamicDisabled ? handleDymicDisabled(time, item) : false"
          :value-format="item.valueFormat ?? 'YYYY-MM-DD'"
          :format="item.valueFormat ?? 'YYYY-MM-DD'"
          @focus="timeEditable"
          @calendar-change="handleCalendarChange"
        />
//点击日期范围外面搜索框
function timeEditable(e: Event) {
  console.log('timeEditable', e)
  // 禁用时间日期范围组件里面的日期input输入框
  nextTick(() => {
    let els = document.querySelectorAll('.el-date-range-picker__time-picker-wrap input')
    console.log('els', els)
    for (var i = 0; i <= els.length - 1; i++) {
      els[i].setAttribute('readonly', 'readonly')
    }
  })

} 

然后发现第一个日期输入框是可以禁止编辑了,但是第二个日期输入框并没有被禁止编辑,就是见了鬼了。加了打印,找到控制台的元素,反复推敲发现了原因。当用户在面板上选择日期的时候,是需要点击两次来确定“开始日期”和“结束日期”的,当点击选择第一个日期之后,第二个日期输入框视图是会被触发重新挂载更新了,导致之前加的readonly丢失,需要再加一遍。因此:

function handleCalendarChange(date: Date[]) {
  console.log('handleCalendarChange', date)
    // 禁用时间日期范围组件里面的日期input输入框
  nextTick(() => {
    let els = document.querySelectorAll('.el-date-range-picker__time-picker-wrap input')
    console.log('els', els)
    for (var i = 0; i <= els.length - 1; i++) {
      els[i].setAttribute('readonly', 'readonly')
    }
  })

}

        在@calendar-change="handleCalendarChange"方法中是触发选择面板的日期的事件方法,在这里再找到所有input,再全部添加一次readonly即可,测试了一下确实验证了我的猜想。至此,终于实现了内输入框的禁用。补充一下,内输入框的时间选择框不受影响,它还是可以选择的。


网站公告

今日签到

点亮在社区的每一天
去签到