1.在components中新建文件夹currency,新建index.js
import Currency from './src/currency.vue'
Currency.install = function (Vue) {
Vue.component(Currency.name, Currency)
}
export default Currency
2.在currency中新建文件夹src,在src中间currency.vue。写入核心代码
<template>
<van-field v-model="liveValue" :name="name" :placeholder="placeholder" :disabled="disabled" :readonly="readonly" @focus="handleFocus" @blur="handleBlur" @change.native="handleChange" v-bind="$attrs" @keydown.native="handleKeydown"></van-field>
</template>
<script>
import { formatter, unFormatter, numberKeyCodes, decimalKeyCodes, plusKeyCodes, minusKeyCodes, operKeyCodes } from '../../currentcy.js'
export default {
name: 'Sjjcurrency',
props: {
name: 'String',
value: {
type: [String, Number],
default: ''
},
format: {
type: String,
default: '16|2'
},
placeholder: String,
separator: {
type: String,
default: ','
},
decimalSymbol: {
type: String,
default: '.'
},
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
},
rounding: {
type: Boolean,
default: false
},
appendKeyCodes: Array,
preFormatter: Function
},
components: {
UnInput
},
data () {
return {
hiddenValue: '', // 合法金额值
liveValue: '' // 展示值
}
},
created () {
let userFormatVal = this.value + ''
if (this.preFormatter) {
userFormatVal = this.preFormatter(userFormatVal)
}
this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat, this.rounding)
this.hiddenValue = unFormatter(this.liveValue, this.separator)
},
watch: {
value (val, oldVal) {
let userFormatVal = this.value + ''
if (this.preFormatter) {
userFormatVal = this.preFormatter(userFormatVal)
}
this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat)
this.hiddenValue = unFormatter(this.liveValue, this.separator)
}
},
methods: {
focus () {
let inputInner = this.$el.querySelector('.van-field_control')
inputInner.focus()
},
blur () {
let inputInner = this.$el.querySelector('.van-field_control')
inputInner.blur()
},
select () {
let inputInner = this.$el.querySelector('.van-field_control')
inputInner.select()
},
handleFocus (event) {
this.liveValue = this.hiddenValue
this.$emit('focus', event)
},
handleBlur (event) {
let userFormatVal = this.liveValue
if (this.preFormatter) {
userFormatVal = this.preFormatter(userFormatVal)
}
this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat, this.rounding)
this.hiddenValue = unFormatter(this.liveValue, this.separator)
this.$emit('input', this.hiddenValue)
this.$nextTick(() => {
this.$emit('blur', event)
})
},
handleChange (val) {
if (/[\u4e00-\u9fa5]/g.test(val)) { // 非IE,忽略可输入的中文
val = this.hiddenValue
}
let userFormatVal = val
if (this.preFormatter) {
userFormatVal = this.preFormatter(val)
}
this.liveValue = formatter(userFormatVal + '', this.separator, this.decimalSymbol, this.format, this.integerFormat, this.rounding)
this.hiddenValue = unFormatter(this.liveValue, this.separator)
this.$emit('input', this.hiddenValue)
this.$nextTick(() => {
this.$emit('change', this.hiddenValue)
})
},
handleKeydown (event) {
if (this.readonly || this.disabled) {
return
}
let keyCode = event.keyCode
if (event.shiftKey) {
keyCode = -9 + '' + keyCode
}
if (event.ctrlKey) {
keyCode = -7 + '' + keyCode
}
// 获取光标位置
let cursurPosition = 0
let inputInner = this.$el.querySelector('.van-field_control')
if (inputInner) {
if (inputInner.selectionStart !== null && inputInner.selectionStart !== undefined) {
// 非IE、IE11
cursurPosition = inputInner.selectionStart
} else {
// IE10-
let range = document.selection.createRange()
range.moveStart('character', -inputInner.val().length)
cursurPosition = range.text.length
}
} else {
cursurPosition = -1
}
keyCode = parseInt(keyCode)
let allowKeyCodes = [
...numberKeyCodes,
...decimalKeyCodes,
...operKeyCodes,
...plusKeyCodes,
...minusKeyCodes
]
if (this.appendKeyCodes && this.appendKeyCodes.length) {
allowKeyCodes = allowKeyCodes.concat(this.appendKeyCodes)
}
// let signalKeyCodes = plusKeyCodes.concat(minusKeyCodes)
if (allowKeyCodes.indexOf(keyCode) < 0 || (this.liveValue.indexOf('.') >= 0 && decimalKeyCodes.indexOf(keyCode) >= 0) || ((this.liveValue.indexOf('+') >= 0 || this.liveValue.indexOf('-') >= 0) && minusKeyCodes.indexOf(keyCode) >= 0) || ((this.liveValue.indexOf('+') >= 0 || this.liveValue.indexOf('-') >= 0) && plusKeyCodes.indexOf(keyCode) >= 0) || (cursurPosition > 0 && plusKeyCodes.concat(minusKeyCodes).indexOf(keyCode) >= 0)) {
event.preventDefault()
} else {
if (cursurPosition === 0 && (plusKeyCodes.indexOf(keyCode) >= 0 || minusKeyCodes.indexOf(keyCode) >= 0)) {
// if ((this.liveValue.indexOf('-') < 0 && minusKeyCodes.indexOf(keyCode) >= 0) || (this.liveValue.indexOf('+') < 0 && plusKeyCodes.indexOf(keyCode) >= 0)) { // 可输入+
if ((this.liveValue.indexOf('-') < 0 && minusKeyCodes.indexOf(keyCode) >= 0)) {
// 不可输入+
} else {
event.preventDefault()
}
}
}
}
}
}
</script>
3.currentcy.js
import { BigDecimal, RoundingMode } from 'bigdecimal'
export const numberKeyCodes = [44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105] // 允许的数字键的keyCode
export const decimalKeyCodes = [190, 110] // 小数键的keyCode
export const plusKeyCodes = [107, -9187] // 正号的keyCode 【小键盘+, 187=(配合shift使用)】
export const minusKeyCodes = [109, 189] // 负号的keyCode
export const operKeyCodes = [9, 46, 8, 37, 39, 35, 36, -767, -786] // 操作特殊字符的KeyCode
function __getIntDigitLength__ (intDigitStr) {
let len = {}
let intLength = ''
let decimalLength = ''
intDigitStr = intDigitStr.trim()
if (intDigitStr && intDigitStr !== '|' && /^(\d*)\|(\d*)$/g.test(intDigitStr)) {
intLength = RegExp.$1
decimalLength = RegExp.$2
len.intLength = intLength
len.decimalLength = decimalLength
return len
} else {
return false
}
}
function __getStringRegExp__ (str) {
try {
if (str && /[\][{}()*+?.\\^$|]/g.test(str)) {
if (str !== '\\') return '\\' + str
else return '\\'
} else return str || ''
} catch (e) {
throw new Error('__getStringRegExp__:' + e.message)
}
}
function __removeSeparator__ (value, separator) {
try {
// var _me = this
var separatorRegExp = __getStringRegExp__(separator) || ''
if (separatorRegExp) {
var dh = new RegExp(separatorRegExp, 'img')
if (value && dh.test(value)) {
return value.replace(dh, '')
}
}
return value || ''
} catch (e) {
throw new Error('__removeSeparator__:' + e.message)
}
}
export function formatter (value, separator, decimalSymbol, intDigitStr, isIntegerOnly, rounding) {
try {
// let valueValid = false
var _currencyValue = {
intLength: '16',
decimalLength: '2',
NegativeValue: '',
intValue: '',
decimalValue: '',
formatValue: ''
}
value = value + ''
if (!value || value === '-' || value === '+') {
return ''
}
// var _me = this,
var separatorRegExp, _value, __decimalLen, __intLen // 整数部分
var lenObj = __getIntDigitLength__(intDigitStr)
if (lenObj) {
_currencyValue.intLength = lenObj.intLength
_currencyValue.decimalLength = lenObj.decimalLength
}
__intLen = parseInt(_currencyValue.intLength, 10)
__decimalLen = rounding ? parseInt(_currencyValue.decimalLength, 10) + 1 : parseInt(_currencyValue.decimalLength, 10)
// var isNegative = false // 是否负数
var valArr = /^-([^-]+)$/.exec(value)
if (valArr) {
// isNegative = true // 表示是负数
_currencyValue.NegativeValue = '-'
value = valArr[1]
}
if (separator === '') {
return ''
}
_value = value // 整数部分
_currencyValue.decimalValue = '' // 小数部分
if (value.indexOf('.') > -1) { // 若含有小数点,则处理得到整数部分和小数部分
_currencyValue.decimalValue = value.substring(value.indexOf('.') + 1)
_value = value.substring(0, value.indexOf('.'))
}
// 若未输入整数部分,则自动取成0----------------------------------------------------
_value = _value === '' ? '0' : _value
// _value === '' ? _value = '0' : _value = _value
if (separator !== '') {
separatorRegExp = __getStringRegExp__(separator)
_value = __removeSeparator__(_value, separator) // 去分隔符
}
if (isNaN(_value) || isNaN(_currencyValue.decimalValue) || isNaN(value)) { // 若不是数字则报错,isNaN('')=false
return ''
}
// modify begin
if (isIntegerOnly && value.indexOf('.') < 0) { // 纯整数格式化且不含.时,对纯整数进行格式化
if (_currencyValue.decimalLength !== '') {
if (_value.length > __decimalLen) {
_currencyValue.decimalValue = _value.substring(_value.length - __decimalLen)
_value = _value.substring(0, _value.length - __decimalLen)
} else {
var _s = _value
for (var i = 0; i < (__decimalLen - _value.length); i++) {
_s = '0' + _s
}
_currencyValue.decimalValue = _s
_value = '0'
}
} else {
_currencyValue.decimalValue = ''
}
} else {
if (_currencyValue.decimalLength !== '') {
if (_currencyValue.decimalValue.length < __decimalLen) {
var _d = _currencyValue.decimalValue
for (var j = 0; j < (__decimalLen - _currencyValue.decimalValue.length); j++) {
_d += '0'
}
_currencyValue.decimalValue = _d
} else {
if (_currencyValue.decimalValue.length > __decimalLen) {
// valueValid = false
}
_currencyValue.decimalValue = _currencyValue.decimalValue.substring(0, __decimalLen)
}
}
}
// modify end
var _intVal = _value
if (_currencyValue.intLength !== '') { // 若存在整数位的限制
if (_currencyValue.intLength < _intVal.length) {
// valueValid = false
}
_intVal = _intVal.substring(0, __intLen)
}
_currencyValue.intValue = _value = _intVal
// 整数处理完毕 end
var _digitpoint = (_currencyValue.decimalValue ? decimalSymbol : '')
let zeroFilter = (_currencyValue.intValue + '').split('').filter(x => {
return x !== '0'
})
if (zeroFilter.length === 0) { // 输入所有位数都是0的情况,设置后直接返回
_currencyValue.intValue = '0'
let zeroFilterDec = (_currencyValue.decimalValue + '').split('').filter(x => {
return x !== '0'
})
// 去掉输入全部为0时的负号
if (zeroFilterDec.length === 0) {
_currencyValue.NegativeValue = ''
}
_currencyValue.formatValue = _currencyValue.NegativeValue + '0' + (_currencyValue.decimalValue !== '' ? (_digitpoint + _currencyValue.decimalValue) : '')
if (rounding) {
_currencyValue.formatValue = new BigDecimal(_currencyValue.formatValue).setScale(__decimalLen - 1, RoundingMode.HALF_UP()).toString()
}
return _currencyValue.formatValue
}
// 处理整数的前缀0
if (/^0+/g.test(_currencyValue.intValue) && !(/^(0+)$/g.test(_currencyValue.intValue)) && !(/^0$/g.test(_currencyValue.intValue))) {
_currencyValue.intValue = _currencyValue.intValue.replace(/^0+/, '')
_value = _intVal = _currencyValue.intValue
}
if (rounding) {
let rVal = _value + _digitpoint + _currencyValue.decimalValue
let roundingVal = new BigDecimal(rVal).setScale(__decimalLen - 1, RoundingMode.HALF_UP()).toString()
_value = roundingVal.substring(0, roundingVal.indexOf(_digitpoint))
_currencyValue.decimalValue = roundingVal.substring(roundingVal.indexOf(_digitpoint) + 1)
}
// 整数部分的分隔符处理开始
if (separator !== '') {
_value = _value + separator
var re = new RegExp('(\\d)(\\d{3}' + separatorRegExp + ')') // 以3个字符串为一组
while (re.test(_value)) {
_value = _value.replace(re, '$1' + separator + '$2')
}
_value = _value.replace(new RegExp(separatorRegExp + '$'), '') // 去掉末尾的分隔符
}
_currencyValue.formatValue = _currencyValue.NegativeValue + _value + (_currencyValue.decimalValue !== '' ? (_digitpoint + _currencyValue.decimalValue) : '')
if (+_currencyValue.formatValue < 0) {
// 去除-号
return _currencyValue.formatValue.substr(1)
} else {
return _currencyValue.formatValue
}
// return _currencyValue.formatValue
} catch (e) {
throw new Error('formatter', e.message)
}
}
export function unFormatter (value, separator) {
return (value + '').replace(new RegExp(separator, 'ig'), '')
}
4.然后就是最愉快的代码引入了(代表10位整数6位小数)
<currency v-model="money" :format="10|6" placeholder="请输入内容" />