vue组件封装 | 数字输入框(限制只能输入数字的input,可以指定小数点位数,最大值、最小值)

目录

s-inputNumber 组件

相关参数


<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>

相关参数

 

猜你喜欢

转载自blog.csdn.net/weixin_41192489/article/details/111903691