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

浙公网安备 33010602011771号