最近接到公司一个需求,输入框输入数字,可按配置自动格式化为千分位分隔,添加相应的前缀与后缀,且保存的数据还是你输入的数据,不是格式化后的数据
所以需要自己封装一个组件,v-model绑定的值是自己输入的原始数据,el-input显示的是格式化后的数据,话不多说,直接上代码
// 组件代码
<template>
<div>
<el-input
ref='oldValue'
v-show="isFocus"
:disabled="item.disabled"
v-model="oldValue"
:placeholder="item.placeholder"
:type="item.formType"
@blur="blur"
@input="input"
></el-input>
<el-input
ref='formatValue'
v-show="!isFocus"
:disabled="item.disabled"
v-model="formatValue"
:maxlength="100"
:placeholder="item.placeholder"
@focus="focus"
></el-input>
</div>
</template>
<script>
// 引入utils里面的格式化方法
import { priceFormat } from '***'
export default {
props: {
value: {
type: [String, Number],
require,
},
item: Object, // 传入的控制数据
},
data() {
return {
isFocus: false, // 是否处于获取焦点状态
formatValue: '',
oldValue: this.value,
}
},
watch: {
oldValue: {
handler(oldValue, newValue) {
// 是否开启千分位分割
const openThousandth = !!this.item?.formatterSchemaDefinition.isShowThousandth
// 前缀
const prefix = this.item.formatterSchemaDefinition?.prefix
// 后缀
const suffix = this.item.formatterSchemaDefinition?.suffix
// 小数位数
const places = this.item?.precisions || 2
this.formatValue = priceFormat( isNaN(this.oldValue) ? this.oldValue : Number(this.oldValue), places, openThousandth, prefix, suffix )
},
immediate: true,
},
value() {
// console.log('asdadadsadasdasdadasda')
this.oldValue = this.value
}
},
methods: {
// 失去焦点
blur(e) {
// console.log('adadasdasdasdadasd')
this.isFocus = false
this.$emit('blur', e)
},
// 获取焦点
async focus(e) {
this.isFocus = true
await this.$nextTick()
// console.log(this.$refs.oldValue, 'this.$refs.oldValue')
this.$refs.oldValue.focus()
this.$emit('focus', e)
},
input() {
console.log('qwewsfdjksdgbhjdbghjdfbj')
this.$emit('input', this.oldValue)
},
},
}
</script>
// 格式化方法
/**
* @Author: ***
* @description: 将数字转换为金额
* @param {*} num: 原始数据
* @param {*} n: 保留的小数位数
* @param {*} openThousandth: 是否开启千分位分隔
* @param {*} prefix: 前缀
* @param {*} suffix: 后缀
* @return {*}
*/
export function priceFormat(num, n, openThousandth, prefix, suffix) {
// 小数点位数
n = n || 2
// 分隔符
let symbol = ","
// num为空时,直接返回
if (num === null || num === undefined || num === '') return num
// 是否为小数
let hasDot = false
// 小数点位数
let m = 0
// 当开启千分位分隔且原始数据为数字时,进行千分位分隔
if(openThousandth && typeof num == 'number') {
if (typeof num !== 'number') throw new TypeError('num参数应该是一个number类型')
if (n < 0) throw new Error('参数n不应该小于0')
hasDot = parseInt(num) != num// 这里检测num是否为小数,true表示小数
m = (n != undefined && n != null) ? n : 1
num = m == 0 ? num.toFixed(m) + '.' : hasDot ? (n ? num.toFixed(n) : num) : num.toFixed(m)
symbol = symbol || ','
num = num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function(match, p1, p2) {
return p1 + symbol
})
}
if (n == 0 || (!hasDot && !n)) { // 如果n为0或者传入的num是整数并且没有指定整数的保留位数,则去掉前面操作中的小数位
num = num.substring(0, num.indexOf('.'))
}
return `${prefix || ''}` + num + `${suffix || ''}`
}
// 使用
<template>
<div>
<formatter-input :item='field' v-model="price" @input="commonChange"/>
</div>
</template>
<script>
// 在需要使用的组件引入
import formatterInput from '***'
export default {
components: {
formatterInput,
},
data() {
return {
field: {
formatterSchemaDefinition: {
isShowThousandth: 1,
prefix: '¥',
suffix: '元',
places: 2,
},
placeholder: '请输入数据,
formType: 'number',
disabled: false
},
price: 0
}
},
methods: {
commonChange(e) {
console.log(e)
}
}
}
</script>