如何在 Element UI DatePicker 中接受较短的用户输入?

How to accept shorter user input into Element UI DatePicker?

在现有代码库中,更新了 ElementUI 和 Vue2 包。用户依赖于过时的 DatePicker UI 组件中看似意外的行为。

在 DatePicker 元素的输入字段中,日期的可视化格式为 30/01/2022。 为了加快输入速度,用户改为在字段中输入 30012022。此行为在更新后消失。只有输入带有 / 分隔符的日期才会被接受。

如何覆盖 ElementUI 日期时间组件的供应商方法以简化输入验证?

替换验证可以通过将 el-date-picker 包装到您自己的组件中来完成。诀窍是在 mounted() 中使用 $nextTick,然后通过包装组件上的 reference 访问要替换的方法。

使用 TypeScript 的 .vue 文件的小代码示例:

<template>
  <el-date-picker
    ref="customDatePicker"
    :type="type"
    :size="size"
    :value="value"
    :clearable="clearable"
    :format="displayFormat"
    :value-format="valueFormat" />
</template>

<script lang="ts">
import moment from 'moment'
import { Component, Prop, Vue } from 'vue-property-decorator'

type PickerType = 'year' | 'month' | 'date' | 'dates' | 'datetime' | ' week' | 'datetimerange' | 'daterange' | 'monthrange'
type Size = 'large' | 'small' | 'mini'

@Component
export default class RexDatePicker extends Vue {
  @Prop()
  readonly value: any

  @Prop({ type: String, default: 'small' })
  readonly size!: Size

  @Prop({ type: String, default: 'date' })
  readonly type!: PickerType

  @Prop({ type: String, default: 'yyyy-MM-dd' })
  readonly valueFormat!: string

  data() {
    return {
      clearable: this.$attrs.clearable !== 'false'
    }
  }

  get displayFormat() : string {
    if (this.type === 'year') {
      return 'yyyy'
    }
    return 'dd/MM/yyyy'
  }

  mounted() {
    this.$nextTick(() => {
      var elPicker: any = this.$refs.customDatePicker
      if (this.type === 'date' || this.type === 'daterange') {
        // inject custom date input behavior
        const originalParseFunction = elPicker.parseString
        elPicker.parseString = function (value) {
          value = expandNumbersToDate(value)
          return originalParseFunction(value)
        }
      }
    })
  }
}

function expandNumbersToDate(value) {
  // expects String, Date or an Array of those two
  if (Object.prototype.toString.call(value) === '[object String]') {
    var currentMonth = moment().format('MM')
    var currentYear = moment().format('YYYY')
    value = value.replace(/^[^\d]*(\d{2})[^\d]*$/, `/${currentMonth}/${currentYear}`)
    value = value.replace(/^[^\d]*(\d{2})(\d{2})[^\d]*$/, `//${currentYear}`)
    value = value.replace(/^[^\d]*(\d{2})\/?(\d{2})\/?(\d{4})[^\d]*$/, '//')
  }
  if (Array.isArray(value)) {
    value = value.map(date => expandNumbersToDate(date))
  }
  return value
}
</script>