目录
<s-inputNumber v-model="height" tip="请输入您的身高" :precision="2" :min="0" :max="3" :step="0.01"/>
data() {
return {
height: null,
}
},
s-inputNumber 组件
默认只能输入整数
事件触发顺序:input change blur
<template>
<div style="display: flex">
<input
class="s-inputNumber"
:disabled="disabled"
:value="myValue"
:placeholder="tip"
@input="input($event)"
@blur="blur($event)"
@change="change($event)"
>
<div v-if="controls && !disabled" class="controlBox">
<div class="controlBnt" @click="increase">
<i class='iconfont icon-icon12' style="font-size: 12px"></i>
</div>
<div class="controlBnt" @click="decrease">
<i class='iconfont icon-icon11' style="font-size: 12px"></i>
</div>
</div>
</div>
</template>
<script>
// js精准计算——两个浮点数求和
function accAdd(num1, num2) {
var r1, r2, m;
try {
r1 = num1.toString().split('.')[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = num2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
return Math.round(num1 * m + num2 * m) / m;
}
// js精准计算——两个浮点数相减
function accSub(num1, num2) {
var r1, r2, m, n;
try {
r1 = num1.toString().split('.')[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = num2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2));
n = (r1 >= r2) ? r1 : r2;
return (Math.round(num1 * m - num2 * m) / m).toFixed(n);
}
export default {
name: "s-inputNumber",
props: {
value: {},
step: {
type: Number,
default: 1
},
max: {
type: Number,
default: Infinity
},
min: {
type: Number,
default: -Infinity
},
disabled: Boolean,
controls: {
type: Boolean,
default: true
},
tip: String,
precision: {
type: Number,
validator(val) {
return val >= 0 && val === parseInt(val, 10);
},
default: 0
}
},
computed: {
myValue() {
let val = this.value === null ? '' : this.value.toString()
// 清除"数字"和"."以及"-"以外的字符
val = val.replace(/[^\-\d.]/g, '')
// 只保留第一个“点”号, 清除多余的
const idx = val.indexOf('.')
if (!(idx === -1 || idx === val.length - 1)) {
val = val.substr(0, idx) + '.' + val.substr(idx + 1).replace(/\./g, '')
}
// 第一个字符如果是.号,则补充前缀0
val = val.replace(/^\./g, '0.')
// 只保留首位的负号, 清除多余的
if (val.length > 1) {
val = val.charAt(0) + val.substr(1).replace(/-/g, '')
}
// 将 '-.' 替换成 '-0.'
val = val.replace(/^\./g, '0.').replace(/^-\./, '-0.')
const str = '^(\\-)*(\\d+)\\.(\\d{' + this.precision + '}).*$'
const reg = new RegExp(str)
if (this.precision === 0) {
// 不需要小数点
val = val.replace(reg, '$1$2')
} else {
// 通过正则保留小数点后指定的位数
val = val.replace(reg, '$1$2.$3')
}
this.$emit('input', val)
return val
}
},
methods: {
increase() {
let val = Number(this.value)
val = accAdd(val, this.step)
if (val < this.min) {
val = this.min
}
if (val > this.max) {
val = this.max
}
this.$emit('input', val)
},
decrease() {
let val = Number(this.value)
val = accSub(val, this.step)
if (val < this.min) {
val = this.min
}
if (val > this.max) {
val = this.max
}
this.$emit('input', val)
},
blur($event) {
let val = Number($event.target.value)
// 只输入负号或未输入时,默认显示最小值
if (isNaN(val) || val === '') {
val = this.min
}
if (val < this.min) {
val = this.min
}
if (val > this.max) {
val = this.max
}
this.$emit('input', val)
this.$emit('blur', val)
},
input($event) {
this.$emit('input', $event.target.value)
},
change($event) {
this.$emit('change', $event.target.value)
},
}
}
</script>
<style scoped>
.controlBnt {
border: 1px solid grey;
cursor: pointer;
font-size: 12px;
}
.s-inputNumber {
height: 30px;
line-height: 30px;
text-align: center;
}
</style>
相关参数