第一次使用官方的uni-numbox,把step设置成小数点,才可以输入小数点。 嗯~~。还是饿了么ElInputNumber组件好用。copy改造了下添加precision控制,小数点就ok了。
template、style不变。其他更多功能去饿了么添加
export default {
name: "UniNumberBox",
emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
props: {
value: {
type: [Number, String],
default: 1
},
modelValue: {
type: [Number, String],
default: 1
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
background: {
type: String,
default: '#f5f5f5'
},
color: {
type: String,
default: '#333'
},
disabled: {
type: Boolean,
default: false
},
// 精度
precision: {
type: Number,
default: 4,
validator(val) {
return val >= 0 && val === parseInt(val, 10);
}
}
},
data() {
return {
inputValue: 0
};
},
watch: {
value(val) {
this.inputValue = +val;
},
modelValue(val) {
this.inputValue = +val;
}
},
computed:{
numPrecision() {
const { value, step, getPrecision, precision } = this;
const stepPrecision = getPrecision(step);
if (precision !== undefined) {
if (stepPrecision > precision) {
// 精度不应小于步长的小数点
console.warn('[Element Warn][InputNumber]precision should not be less than the decimal places of step');
}
return precision;
} else {
return Math.max(getPrecision(value), stepPrecision);
}
},
},
created() {
if (this.value === 1) {
this.inputValue = +this.modelValue;
}
if (this.modelValue === 1) {
this.inputValue = +this.value;
}
},
methods: {
getPrecision(value) {
if (value === undefined) return 0;
const valueString = value.toString();
const dotPosition = valueString.indexOf('.');
let precision = 0;
if (dotPosition !== -1) {
precision = valueString.length - dotPosition - 1;
}
return precision;
},
toPrecision(num, precision) {
if (precision === undefined) precision = this.numPrecision;
return parseFloat(Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision));
},
_increase(val, step) {
if (typeof val !== 'number' && val !== undefined) return this.currentValue;
const precisionFactor = Math.pow(10, this.numPrecision);
// Solve the accuracy problem of JS decimal calculation by converting the value to integer.
return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor);
},
_decrease(val, step) {
if (typeof val !== 'number' && val !== undefined) return this.inputValue;
const precisionFactor = Math.pow(10, this.numPrecision);
return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor);
},
setCurrentValue(newVal) {
const oldVal = this.value;
if (typeof newVal === 'number' && this.precision !== undefined) {
newVal = this.toPrecision(newVal, this.precision);
}
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
if (oldVal === newVal) return this.value;
this.$emit("change", newVal);
// TODO vue2 兼容
this.$emit("input", newVal);
// TODO vue3 兼容
this.$emit("update:modelValue", newVal);
this.inputValue = newVal;
},
_calcValue(type) {
if (this.disabled) {
return;
}
if (type === "minus") {
this.decrease()
}
if (type === "plus") {
this.increase()
}
},
increase() {
// if (this.inputNumberDisabled || this.maxDisabled) return;
const value = this.value || 0;
const newVal = this._increase(value, this.step);
this.setCurrentValue(newVal);
},
decrease() {
// if (this.inputNumberDisabled || this.minDisabled) return;
const value = this.value || 0;
const newVal = this._decrease(value, this.step);
this.setCurrentValue(newVal);
},
_onBlur(event) {
this.$emit('blur', event)
let value = event.detail.value;
if (!value) {
// this.inputValue = 0;
return;
}
this.inputValue = this.setCurrentValue(this.toPrecision(value, this.precision));
},
_onFocus(event) {
this.$emit('focus', event)
}
}
};