【无标题】

vue项目实现数字区间输入组件

前言

公司要求检索项必须是个数字区间,而且可以支持负数输入,写了几个都不理想,最后参考网上一些资料封装成了一个组件。
参考链接:Element基于el-input数字范围输入框的实现

numberRange.vue文件夹

<template>
  <div class="input-number-range" :class="{ 'is-disabled': disabled }">
    <div class="flex">
      <el-input
        ref="inputFromRef"
        clearable
        v-model="startData"
        :disabled="disabled"
        :placeholder="startPlaceholder"
        @blur="handleBlurFrom"
        @focus="handleFocusFrom"
        @input="handleInputFrom"
        @change="handleInputChangeFrom"
        v-bind="$attrs"
        v-on="$listeners"
      >
        <template v-for="(value, name) in startSlots" #[name]="slotData">
          <slot :name="name" v-bind="slotData || {}"></slot>
        </template>
      </el-input>
      <div class="center">
        <span></span>
      </div>
      <el-input
        ref="inputToRef"
        clearable
        v-model="endData"
        :disabled="disabled"
        :placeholder="endPlaceholder"
        @blur="handleBlurTo"
        @focus="handleFocusTo"
        @input="handleInputTo"
        @change="handleInputChangeTo"
        v-bind="$attrs"
        v-on="$listeners"
      >
        <template v-for="(value, name) in endSlots" #[name]="slotData">
          <slot :name="name" v-bind="slotData || {}"></slot>
        </template>
      </el-input>
    </div>
  </div>
</template>
<script>
import URLToolkit from 'hls.js';

export default {
  name: 'InputNumberRange',
  props: {
    // inputs: {
    //   type: Array,
    //   required: true,
    //   default: () => [null, null],
    // },
    startValue: {
      type: [Number, String],
      default: null,
    },
    endValue: {
      type: [Number, String],
      default: null,
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    startPlaceholder: {
      type: String,
      default: '最小值',
    },
    endPlaceholder: {
      type: String,
      default: '最大值',
    },
    // 精度参数
    precision: {
      type: Number,
      default: 0,
      validator(val) {
        return val >= 0 && val === parseInt(val, 10);
      },
    },
  },
  data() {
    return {
      startData: this.startValue,
      endData: this.endValue,
    };
  },
  watch: {
    startValue(val, oldVal) {
      if (val === null) {
        this.startData = null;
      }
    },
    endValue(val, oldVal) {
      if (val === null) {
        this.endData = null;
      }
    },
  },
  computed: {
    startSlots() {
      const slots = {};
      Object.keys(this.$slots).forEach(name => {
        if (name.startsWith('start-')) {
          const newKey = name.replace(/^start-/, '');
          slots[newKey] = this.$slots[name];
        }
      });
      return slots;
    },
    endSlots() {
      const slots = {};
      Object.keys(this.$slots).forEach(name => {
        if (name.startsWith('end-')) {
          const newKey = name.replace(/^end-/, '');
          slots[newKey] = this.$slots[name];
        }
      });
      return slots;
    },
  },
  methods: {
    // 重置
    resetting() {
      this.formDataUpdate();
      this.endDataUpdate();
    },
    handleInputFrom(value) {
      this.$emit('update:startValue', value);
    },
    handleInputTo(value) {
      this.$emit('update:endValue', value);
    },
    // 更新start数据
    formDataUpdate(data = null) {
      this.$emit('update:startValue', data);
      this.startData = data;
    },
    // 更新end数据
    endDataUpdate(data = null) {
      this.$emit('update:endValue', data);
      this.endData = data;
    },
    // from输入框change事件
    handleInputChangeFrom(value) {
      // 如果是非数字空返回null
      if (value == '' || isNaN(value)) {
        // this.$emit('update:startValue', null);
        this.formDataUpdate(null);
        return;
      }
      // 初始化数字精度
      const newStartValue = this.setPrecisionValue(value);
      // 如果from > to 将from值替换成to
      if (
        typeof newStartValue === 'number' &&
        parseFloat(newStartValue) > parseFloat(this.endData)
      ) {
        // this.startData = this.endData;
        this.formDataUpdate(this.endData);
      } else {
        // this.startData = newStartValue;
        this.formDataUpdate(newStartValue);
      }
      if (this.startData !== value) {
        // this.$emit('update:startValue', this.startData);
        this.formDataUpdate(this.startData);
      }
    },
    // to输入框change事件
    handleInputChangeTo(value) {
      // 如果是非数字空返回null
      if (value == '' || isNaN(value)) {
        // this.$emit('update:endValue', null);
        this.endDataUpdate(null);
        return;
      }
      // 初始化数字精度
      const newEndValue = this.setPrecisionValue(value);
      // 如果from > to 将from值替换成to
      if (
        typeof newEndValue === 'number' &&
        parseFloat(newEndValue) < parseFloat(this.startData)
      ) {
        // this.endData = this.startData;
        this.endDataUpdate(this.startData);
      } else {
        // this.endData = newEndValue;
        this.endDataUpdate(newEndValue);
      }
      if (this.endData !== value) {
        // this.$emit('update:endValue', this.endData);
        this.endDataUpdate(this.endData);
      }
    },
    handleBlurFrom(event) {
      this.$emit('blur-from', event);
    },
    handleFocusFrom(event) {
      this.$emit('focus-from', event);
    },
    handleBlurTo(event) {
      this.$emit('blur-to', event);
    },
    handleFocusTo(event) {
      this.$emit('focus-to', event);
    },
    // 根据精度保留数字
    toPrecision(num, precision) {
      if (precision === undefined) precision = 0;
      return parseFloat(
        Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision)
      );
    },
    // 设置精度
    setPrecisionValue(value) {
      if (this.precision === undefined) return value;
      return this.toPrecision(parseFloat(value), this.precision);
    },
  },
};
</script>
<style lang="scss" scoped>
// 取消element原有的input框样式
::v-deep .el-input__inner {
  border: 0px;
  margin: 0;
  padding: 0 15px;
  background-color: transparent;

  position: relative !important;
  caret-color: #333;
  box-sizing: border-box;
  // font: 600 0.22rem/0.3rem PingFangSC-Regular, PingFang SC;
  color: #333;
}
::v-deep .el-input__inner::-webkit-input-placeholder {
  position: absolute !important;
  // top: 0.04rem !important;
  top: 25%;
  // transform: translateY(-50%);
  // font: 400 0.16rem PingFangSC-Regular, PingFang SC;
  color: #b2b2b2 !important;
  left: 50%;
  transform: translateX(-50%);
}
.input-number-range {
  background-color: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}
.flex {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: auto;
  justify-content: center;
  align-items: center;
  .center {
    margin-top: 1px;
  }
}
.is-disabled {
  background-color: #f5f7fa;
  border-color: #e4e7ed;
  color: #c0c4cc;
  cursor: not-allowed;
}
</style>

父组件使用

  <numberRange :startValue.sync="startValue" :endValue.sync="endValue"/>

Ps:

仅供参考,可根据具体需求加以改造

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值