elementui vue2 数值范围输入框

429 阅读1分钟

 效果

image.png

使用

注意:使用element el-form el-form-item 包裹组件后,会自动添加范围校验规则。另由于我不需要其他功能,所以没有处理input的各种事件。

<el-form ref="volatilityFormRef" :disabled="!volatility.checked" label-width="7rem" :model="volatility.data" :rules="volatility.rules" size="medium">
    <el-form-item label="波动范围" prop="range">
        <input-number-range v-model="volatility.data.range" :disabled="!volatility.checked" unit="%"></input-number-range>
    </el-form-item>
</el-form>

组件代码

<template>
  <el-row v-auto-range-validate class="input-number-range" :class="{ 'is-disabled': disabled }" justify="space-between" type="flex">
    <el-input v-model.trim="value[0]" v-q-number :disabled="disabled" placeholder="最小值" :size="size" type="text">
      <template v-if="unit" v-slot:append>
        <span>{{ unit }}</span>
      </template>
    </el-input>
    <span :class="{ 'is-disabled': disabled }">{{ precision }}</span>
    <el-input v-model.trim="value[1]" v-q-number :disabled="disabled" placeholder="最大值" :size="size" type="text">
      <template v-if="unit" v-slot:append>
        <span>{{ unit }}</span>
      </template>
    </el-input>
  </el-row>
</template>

<script>
export default {
  name: "InputNumberRange",
  directives: {
    "auto-range-validate": {
      inserted(el, binding, vnode) {
        const _this = vnode.context
        let formItem = _this
        while (formItem && formItem.$options.name !== "ElFormItem") {
          formItem = formItem.$parent
          if (!formItem) break
        }
        if (!formItem) return
        const prop = formItem.prop
        const form = formItem.$parent
        if (!prop || !form) return
        let rules = form.rules
        if (!rules) form.rules = rules = { [prop]: [] }
        if (!rules[prop]) rules[prop] = []
        if (!Array.isArray(rules[prop])) rules[prop] = [rules[prop]]
        rules[prop].push({
          validator: (rule, value, callback) => {
            const msg = _this.validate()
            callback(msg ? new Error(msg) : "")
          },
          trigger: "blur",
        })
      },
    },
  },
  model: {
    prop: "value",
    event: "onChange",
  },
  emits: ["onChange"],
  props: {
    value: {
      type: [Array],
      default: () => [null, null],
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    size: {
      type: String,
      default: "medium",
      validator: (val) => ["mini", "small", "medium"].includes(val),
    },
    separator: {
      type: String,
      default: "至",
    },
    unit: {
      type: String,
      default: "",
    },
    precision: {
      type: Number,
      default: null,
    },
  },

  data() {
    return {}
  },
  watch: {
    value: {
      handler(val) {
        this.$nextTick(() => {
          if (!Array.isArray(val) || val.length !== 2) {
            // 第一次 修正value值
            this.$emit("onChange", [null, null])
          }
        })
      },
      immediate: true,
    },
  },
  methods: {
    validate() {
      const min = this.value[0]
      const max = this.value[1]
      if (!min && !max) return ""
      if (!min) return "请输入最小值"
      if (!max) return "请输入最大值"
      if (parseFloat(min) > parseFloat(max)) return "最小值不能大于最大值"
      if (this.precision !== 0 && !this.precision) return
      this.$emit("onChange", [parseFloat(min).toFixed(this.precision), parseFloat(max).toFixed(this.precision)])
    },
  },
}
</script>
<style lang="stylus" scoped>
.input-number-range
  background-color #fff
  border 1px solid #dcdfe6
  border-radius 4px

  .is-disabled
    background-color #eef0f6
    border-color #e4e7ed
    color #c0c4cc
    cursor not-allowed
    /deep/.el-input-group__append
      background-color inherit
      color inherit

  // 取消element原有的input框样式
  /deep/.el-input
    .el-input__inner
      border 0
      margin 0
      padding 0 15px
      background-color transparent
      text-align center
  /deep/.el-input-group__append
    background-color #fff
    border unset
</style>

另一个自定义指令

// 输入框有理数   注意自行注册
export const QNumber = {
  inserted: function (el) {
    const inputEl = el.querySelector("input")
    if (inputEl) {
      inputEl.addEventListener("input", function () {
        const reg = /^-?(0|[1-9]\d*)(.\d*)?$/
        let value = inputEl.value
        value = value.replace(/[^\d.-]/g, "")
        if (!reg.test(value) && value !== "") {
          inputEl.value = ""
        } else {
          inputEl.value = value
        }
      })
    }
  },
}