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:
仅供参考,可根据具体需求加以改造