vue中input 保留两位小数
1. 把NumericInput.vue文件添加至src/compontents目录下(NumericInput.vue是 自己封装的一个组件) 内容如下<!--Originally copied from Vue-Numeric (MIT licensed)Using el-input instead to make el-form validation availab...
·
1. 把NumericInput.vue文件添加至src/compontents目录下(NumericInput.vue是 自己封装的一个组件) 内容如下
<!--
Originally copied from Vue-Numeric (MIT licensed)
Using el-input instead to make el-form validation available
(using input does not work)
-->
<template>
<el-input
:placeholder="placeholder"
@blur="onBlurHandler"
@input="onInputHandler"
@focus="onFocusHandler"
ref="numeric"
type="tel"
v-model="amount"
v-if="!readOnly"
></el-input>
<span
v-else
ref="readOnly"
>{{ amount }}</span>
</template>
<script>
import accounting from 'accounting-js'
export default {
name: 'NumericInput',
props: {
/**
* Currency symbol.
*/
currency: {
type: String,
default: '',
required: false
},
/**
* Maximum value allowed.
*/
max: {
type: Number,
default: Number.MAX_SAFE_INTEGER || 9007199254740991,
required: false,
},
/**
* Minimum value allowed.
*/
min: {
type: Number,
default: Number.MIN_SAFE_INTEGER || -9007199254740991,
required: false
},
/**
* Enable/Disable minus value.
*/
minus: {
type: Boolean,
default: false,
required: false
},
/**
* Input placeholder.
*/
placeholder: {
type: String,
default: '',
required: false
},
/**
* Value when the input is empty
*/
emptyValue: {
type: [Number, String],
default: '',
required: false
},
/**
* Number of decimals.
* Decimals symbol are the opposite of separator symbol.
*/
precision: {
type: Number,
default: 0,
required: false
},
/**
* Thousand separator type.
* Separator props accept either . or , (default).
*/
separator: {
type: String,
default: ',',
required: false
},
/**
* Forced thousand separator.
* Accepts any string.
*/
thousandSeparator: {
default: undefined,
required: false,
type: String
},
/**
* Forced decimal separator.
* Accepts any string.
*/
decimalSeparator: {
default: undefined,
required: false,
type: String
},
/**
* The output type used for v-model.
* It can either be String or Number (default).
*/
outputType: {
required: false,
type: String,
default: 'Number'
},
/**
* v-model value.
*/
value: {
type: [Number, String],
default: 0,
required: true
},
/**
* Hide input and show value in text only.
*/
readOnly: {
type: Boolean,
default: false,
required: false
},
/**
* Class for the span tag when readOnly props is true.
*/
readOnlyClass: {
type: String,
default: '',
required: false
},
/**
* Position of currency symbol
* Symbol position props accept either 'suffix' or 'prefix' (default).
*/
currencySymbolPosition: {
type: String,
default: 'prefix',
required: false
}
},
data: () => ({
amount: ''
}),
computed: {
/**
* Number type of formatted value.
* @return {Number}
*/
amountNumber () {
return this.unformat(this.amount)
},
/**
* Number type of value props.
* @return {Number}
*/
valueNumber () {
return this.unformat(this.value)
},
/**
* Define decimal separator based on separator props.
* @return {String} '.' or ','
*/
decimalSeparatorSymbol () {
if (typeof this.decimalSeparator !== 'undefined') return this.decimalSeparator
if (this.separator === ',') return '.'
return ','
},
/**
* Define thousand separator based on separator props.
* @return {String} '.' or ','
*/
thousandSeparatorSymbol () {
if (typeof this.thousandSeparator !== 'undefined') return this.thousandSeparator
if (this.separator === '.') return '.'
if (this.separator === 'space') return ' '
return ','
},
/**
* Define format position for currency symbol and value.
* @return {String} format
*/
symbolPosition () {
if (!this.currency) return '%v'
return this.currencySymbolPosition === 'suffix' ? '%v %s' : '%s %v'
}
},
watch: {
/**
* Watch for value change from other input with same v-model.
* @param {Number} newValue
*/
// valueNumber (newValue) {
// if (this.$refs.numeric !== document.activeElement) {
// this.amount = this.format(newValue)
// }
// },
/**
* When readOnly is true, replace the span tag class.
* @param {Boolean} newValue
* @param {Boolean} oldValue
*/
readOnly (newValue, oldValue) {
if (oldValue === false && newValue === true) {
this.$nextTick(() => {
this.$refs.readOnly.className = this.readOnlyClass
})
}
},
/**
* Immediately reflect separator changes
*/
separator () {
this.process(this.valueNumber)
this.amount = this.format(this.valueNumber)
},
/**
* Immediately reflect currency changes
*/
currency () {
this.process(this.valueNumber)
this.amount = this.format(this.valueNumber)
},
/**
* Immediately reflect precision changes
*/
precision () {
this.process(this.valueNumber)
this.amount = this.format(this.valueNumber)
}
},
mounted () {
// Set default value props when placeholder undefined.
if (!this.placeholder) {
this.process(this.valueNumber)
this.amount = this.format(this.valueNumber)
// In case of delayed props value.
setTimeout(() => {
this.process(this.valueNumber)
this.amount = this.format(this.valueNumber)
}, 500)
}
// Set read-only span element's class
if (this.readOnly) this.$refs.readOnly.className = this.readOnlyClass;
(function($) {
$.fn.inputFilter = function(inputFilter) {
return this.on("input keydown keyup", function() {
if (inputFilter(this.value)) {
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
} else if (this.hasOwnProperty("oldValue")) {
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
}
});
};
}($));
$(this.$el.children[0]).inputFilter(function(value) {
return /^-?\d*[.,]?\d{0,2}$/.test(value);
});
},
methods: {
/**
* Handle blur event.
* @param {Object} e
*/
onBlurHandler (e) {
this.$emit('blur', e)
this.amount = this.format(this.valueNumber)
},
/**
* Handle focus event.
* @param {Object} e
*/
onFocusHandler (e) {
this.$emit('focus', e)
if (this.valueNumber === 0) {
this.amount = null
} else {
this.amount = accounting.formatMoney(this.valueNumber, {
symbol: '',
format: '%v',
thousand: '',
decimal: this.decimalSeparatorSymbol,
precision: Number(this.precision)
})
}
},
/**
* Handle input event.
*/
onInputHandler () {
this.process(this.amountNumber)
},
/**
* Validate value before update the component.
* @param {Number} value
*/
process (value) {
if (value >= this.max) this.update(this.max)
if (value <= this.min) this.update(this.min)
if (value > this.min && value < this.max) this.update(value)
if (!this.minus && value < 0) this.min >= 0 ? this.update(this.min) : this.update(0)
},
/**
* Update parent component model value.
* @param {Number} value
*/
update (value) {
const fixedValue = accounting.toFixed(value, this.precision)
const output = this.outputType.toLowerCase() === 'string' ? fixedValue : Number(fixedValue)
this.$emit('input', output)
},
/**
* Format value using symbol and separator.
* @param {Number} value
* @return {String}
*/
format (value) {
return accounting.formatMoney(value, {
symbol: this.currency,
format: this.symbolPosition,
precision: Number(this.precision),
decimal: this.decimalSeparatorSymbol,
thousand: this.thousandSeparatorSymbol
})
},
/**
* Remove symbol and separator.
* @param {Number} value
* @return {Number}
*/
unformat (value) {
const toUnformat = typeof value === 'string' && value === '' ? this.emptyValue : value
return accounting.unformat(toUnformat, this.decimalSeparatorSymbol)
},
init(){
this.amount = '';
}
}
}
</script>
2. 安装依赖 npm install accounting-js (原因是NumericInput.vue中引入了accounting-js)
3. 在xxx.vue中引入并声明组件
<script>
import numericInput from '../components/NumericInput'
export default {
components: {
numericInput
},
}
</script>
5. 使用方法
1)把<input>替换为<numeric-input></numeric-input>
2)precision属性加上即可
<numeric-input v-model="price" :precision="2"></numeric-input>
element-ui 替换<el-input>
<el-form-item label="价钱" prop="price">
// 替换之后的 precision 表示保留几位小数
<numeric-input v-model="ruleForm2.price" :precision="2"></numeric-input>
// 之前的
<!-- <el-input v-model="ruleForm2.price"></el-input> -->
</el-form-item>
更多推荐
已为社区贡献8条内容
所有评论(0)