支持千分符的自定义组件input

  1、组件的实现逻辑代码

  暂且将文件名称为thousand-bit-input.vue

<template>
    <div>
        <input :class="thousandBitInputClass"
            :disabled="disabled"
            :placeholder="placeholder"
            :required="innerRquried"
            :type="type"
            :aria-label="label"
            :value="value" 
            @input="$emit('input', $event.target.value)"
            @change="$emit('change', $event)"
            @blur="blur">
        <div class="commafy-div__error" v-if="showError">{{ errorTip }}</div>
        <div class="commafy-div__error" v-else-if="showRequired">{{ requiredTip }}</div>
    </div>
</template>

<script>
import Vue from 'vue'
export default {
    name: 'thousand-bit-input',
    model: {
        prop: 'value',
        event: 'input'
    },
    props: {
        value: {
            type: [String, Number]
        },
        type: {
            type: String,
            default: 'text'
        },
        label: {
            type: String,
            default: ''
        },
        disabled: {
            type: Boolean,
            default: false
        },
        placeholder: {
            type: String,
            default: ''
        },
        required: {
            type: Boolean,
            default: false
        },
        requiredTip: {
            type: String,
            default: ''
        }
    },
    data() { 
        return {
            errorTip: '请输入数字值,最多保留两位小数',
            showError: false,
            showRequired: false,
            innerRquried: this.required
        }
    },
    computed: {
        thousandBitInputClass: function() {
            let self = this
            let inputClass = {'thousand-bit-input__inner': true}
            if (self.required) {
                if (self.value) {
                    inputClass['thousand-bit-input__inner_error'] = self.showError
                    self.innerRquried = false
                    self.showRequired = false
                } else {
                    self.innerRquried = true
                    self.showError = false
                    self.showRequired = true
                }
            } else {
                self.innerRquried = false
                inputClass['thousand-bit-input__inner_error'] = self.showError
            }
            return inputClass
        }
    },
    watch: {
        required: {
            handler: function(newVal, oldVal) {
                this.innerRquried = newVal
                this.showRequired = newVal
            },
            immediate: true
        },
        value: {
            handler: function(newVal, oldVal) {
                if (newVal) {
                    let numberPattern = /^((?:-?0)|(?:-?[1-9]\d*))(?:\.\d{1,2})?$/
                    let numberThousandsPattern = /^((?:-?0)|(?:-?[1-9]\d*)|(?:-?[1-9],\d{3})?)(?:,\d{3})*(?:\.\d{1,2})?$/
                    let testNumber = value => {
                        if (numberPattern.test(value)) {
                            this.showError = false
                        } else {
                            this.showError = true
                        }
                    }
                    newVal = newVal + ''
                    let index = newVal.indexOf(',')
                    if (index === -1) {
                        testNumber(newVal)
                    } else {
                        if (numberThousandsPattern.test(newVal)) {
                            this.showError = false
                        } else {
                            index = newVal.lastIndexOf(',')
                            if (index === newVal.length - 1) {
                                this.showError = true
                            }
                            newVal = newVal.replace(/,/g, '')
                            testNumber(newVal)
                        }
                    }
                } else {
                    this.showError = false
                }
                if (this.showError === false && newVal) {
                    let num = newVal + ''
                    if (num.trim() === '') {
                        return ''
                    }
                    let index = num.indexOf('.')
                    let intPart = ''
                    let floatPart = ''
                    if (index !== -1) {
                        intPart = num.substr(0, index)
                        floatPart = num.substr(index)
                    } else {
                        intPart = num
                    }
                    intPart = intPart.replace(/,/g, '')
                    let intPartReverse = intPart.split('').reverse()
                    let length = intPartReverse.length
                    let formatNumber = ''
                    for (let i = 0; i < length; i++) {
                        formatNumber += intPartReverse[i] + ((i + 1) % 3 === 0 && (i + 1) !== length ? ',' : '')
                    }
                    let formatNumber = formatNumber.split('').reverse().join('') + floatPart
                    formatNumber = formatNumber.replace(/^-,/, '-')
                    this.$emit('input', formatValue)
                }
            },
            immediate: true
        }
    },
    methods: {
        blur(event) {
            let value = this.value
            value = this.$global.Number.toFixedTwo(value)
            this.$emit('input', value)
            this.$emit('blur', event)
        }
    }
}
</script>

<style scoped>
.thousand-bit-input__inner {
    background-color: #fff;
    background-image: none;
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    box-sizing: border-box;
    color: #606266;
    display: inline-block;
    height: 32px;
    line-height: 32px;
    padding: 0 15px;
    transition: border-color .2s cubic-bezier(.645,.045,.355,1);
    width: 100%;
}
.thousand-bit-input__inner:hover {
    border-color: #c0c4cc;
}
.thousand-bit-input__inner:focus {
    border-color: #409EFF;
}
.thousand-bit-input__inner:required,
.thousand-bit-input__inner_error,
.thousand-bit-input__inner_error:hover,
.thousand-bit-input__inner_error:focus {
    border-color: #f56c6c;
}
.thousand-bit-input__inner:disabled {
    background-color: #f5f7fa;
    border-color: #e4e7ed;
    color: #c0c4cc;
    cursor: not-allowed;
}
input::-webkit-input-placeholder {
    color: #c0c4cc;
}
input::-moz-input-placeholder {
    color: #c0c4cc;
}
input::-ms-input-placeholder {
    color: #c0c4cc;
}
.commafy-div__error {
    color: #f56c6c;
    font-size: 12px;
    line-height: 1;
    position: absolute;
    top: 100%;
    left: 0;
}
</style>

  2、组件的使用

  • 在main.js文件中注册为全局组件:
import thousandBitInput from 'thousand-bit-input'

Vue.component('thousand-bit-input', thousandBitInput)
  • 在需要的文件中使用该组件:
<thousand-bit-input v-model="name" :disabled="disabled" :required="requried"
   :placeholder="请输入名称"></thousand-bit-input>

   3、说明

  该组件可以直接在项目工程中使用,并且是实时动态转换的。

posted @ 2020-04-13 19:43  晒太阳的兔子很忙  阅读(298)  评论(0编辑  收藏  举报