numberinput
This commit is contained in:
85
components/LimitInput.vue
Normal file
85
components/LimitInput.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="fxcol">
|
||||
<input
|
||||
class="filter-input i-border"
|
||||
:disabled="disabled"
|
||||
:type="type"
|
||||
ref="input"
|
||||
:value="numberValue"
|
||||
:placeholder="placeholder"
|
||||
oninput="value=value.replace(/[^\d.]/g,'')"
|
||||
@input="handleChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'limitInput',
|
||||
props: {
|
||||
disabled: Boolean,
|
||||
type: String,
|
||||
placeholder: String,
|
||||
value: '', // 传过来的值
|
||||
max: Number,
|
||||
min: Number,
|
||||
defaultValue: '' // 默认值
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
numberValue: this.value
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) { // 监听传来的value值,并传递给新定义的值
|
||||
// debugger
|
||||
this.numberValue = Number(val)
|
||||
},
|
||||
max (val) { // 因为最大值是根据上个值输入而变化的,所以要监听相应变化
|
||||
this.max = val
|
||||
},
|
||||
min (val) { // 因为最小值是根据上个值输入而变化的,所以要监听相应变化
|
||||
this.min = val
|
||||
},
|
||||
numberValue (val) { // emit input事件,可令父组件进行v-model绑定
|
||||
this.$emit('input', val)
|
||||
},
|
||||
disabled (val) {
|
||||
this.disabled = val
|
||||
},
|
||||
defaultValue (val) { // 要根据上面的值变化而相应变化,所以要监听
|
||||
this.numberValue = val
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange (event) {
|
||||
let val = event.target.value.trim()
|
||||
if (val < 0 || isNaN(val)) {
|
||||
this.numberValue = 0
|
||||
return
|
||||
}
|
||||
if (val) {
|
||||
val = Number(val)
|
||||
this.numberValue = val
|
||||
if (val > Number(this.max)) this.numberValue = this.max
|
||||
if (val < Number(this.min)) this.numberValue = this.min
|
||||
} else {
|
||||
this.numberValue = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.defaultValue) {
|
||||
this.numberValue = this.defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
// input
|
||||
// width 100%
|
||||
.i-border
|
||||
border 1px solid #a1a1a1
|
||||
border-radius 3px
|
||||
text-align center
|
||||
</style>
|
||||
123
components/NumberInput.vue
Normal file
123
components/NumberInput.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<!-- components/number-input.vue -->
|
||||
<template>
|
||||
<input
|
||||
type="text"
|
||||
:value="displayValue"
|
||||
@input="handleInput"
|
||||
@blur="handleBlur"
|
||||
:placeholder="placeholder"
|
||||
:class="inputClass"
|
||||
:style="inputStyle"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "NumberInput",
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0.001
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100000
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请输入大于0的数字'
|
||||
},
|
||||
inputClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
inputStyle: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
displayValue: this.value.toString()
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
// 当外部value变化时更新显示值
|
||||
this.displayValue = newVal.toString();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInput(e) {
|
||||
const rawValue = e.detail.value;
|
||||
let filtered = rawValue
|
||||
// 移除非数字和小数点的字符
|
||||
.replace(/[^\d.]/g, '')
|
||||
// 只保留第一个小数点
|
||||
.replace(/(\.+)/g, '.')
|
||||
.replace(/(\..*)\./g, '$1')
|
||||
// 避免以0开头(0后面没有小数点的情况)
|
||||
.replace(/^0+(\d)/, '$1');
|
||||
|
||||
// 处理开头是小数点的情况(添加0前缀)
|
||||
if (filtered.startsWith('.')) {
|
||||
filtered = '0' + filtered;
|
||||
}
|
||||
|
||||
this.displayValue = filtered;
|
||||
this.$emit('input', filtered);
|
||||
},
|
||||
|
||||
handleBlur() {
|
||||
let finalValue = this.displayValue;
|
||||
|
||||
// 空值处理
|
||||
if (!finalValue) {
|
||||
finalValue = this.min.toString();
|
||||
}
|
||||
|
||||
// 处理以小数点结尾的情况
|
||||
if (finalValue.endsWith('.')) {
|
||||
finalValue = finalValue.slice(0, -1);
|
||||
}
|
||||
|
||||
// 转换为数字
|
||||
let numValue = parseFloat(finalValue);
|
||||
|
||||
// 验证数字有效性
|
||||
if (isNaN(numValue)) {
|
||||
numValue = this.min;
|
||||
}
|
||||
|
||||
// 边界校验
|
||||
if (numValue <= 0) {
|
||||
numValue = this.min;
|
||||
} else if (numValue > this.max) {
|
||||
numValue = this.max;
|
||||
} else if (numValue < this.min) {
|
||||
numValue = this.min;
|
||||
}
|
||||
|
||||
// 小数位处理(最多3位)
|
||||
const numStr = numValue.toString();
|
||||
const decimalIndex = numStr.indexOf('.');
|
||||
if (decimalIndex !== -1) {
|
||||
const decimalPart = numStr.slice(decimalIndex + 1);
|
||||
if (decimalPart.length > 3) {
|
||||
// 直接截断而非四舍五入
|
||||
numValue = parseFloat(numStr.substring(0, decimalIndex + 4));
|
||||
}
|
||||
}
|
||||
|
||||
// 更新显示值并通知父组件
|
||||
this.displayValue = numValue.toString();
|
||||
this.$emit('input', numValue);
|
||||
this.$emit('change', numValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user