支持千分符的自定义组件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、说明
该组件可以直接在项目工程中使用,并且是实时动态转换的。
阅读是一种修养,分享是一种美德。