vue中使用自定义金额格式化组件,对金额进行千分位格式化
分两种情况:不使用vue/cli脚手架搭建和使用vue/cli脚手架搭建的项目
一、不使用vue/cli脚手架搭建
1、该组件基于vue,element,accountingjs
2、引入相应的js文件
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> <script src="https://cdn.bootcss.com/accounting.js/0.4.1/accounting.js"></script> <!-- 引入样式 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <!-- 引入组件库 --> <script src="https://unpkg.com/element-ui/lib/index.js"></script>
3、如何使用:html部分
<div id="app"> <div style="display:inline-block"> <currency-input v-model="price" :decimal="4" style="width:200px;" @blur="inputBlur"></currency-input> <el-button type="primary" size="small" @click="submit">提交</el-button> </div> </div>
4、如何使用:js部分
Vue.component('currency-input', {
template: '\
<div class="el-input el-input--small" v-bind:class="{\'is-disabled\':disabled}">\
<input\
ref="input"\
v-bind:value="formatValue"\
v-on:input="onInput($event.target.value)"\
v-on:focus="selectAll"\
v-on:blur="onBlur"\
v-bind:disabled="disabled"\
class="el-input__inner"\
>\
</div>\
',
props: {
value: {
type: [String, Number],
default: 0,
desc: '数值'
},
symbol: {
type: String,
default: "",
desc: '货币标识符'
},
decimal: {
type: Number,
default: 2,
desc: '小数位'
},
disabled: {
type: Boolean,
default: false,
desc: "是否禁止"
}
},
data() {
return {
focused: false
};
},
computed: {
formatValue() {
if (this.focused) {
return this.$accounting.unformat(this.value);
} else {
return this.$accounting.formatMoney(this.value, this.symbol, this.decimal);
}
}
},
watch: {
value(val) {if (this.validateEvent) {
this.dispatch('ElFormItem', 'el.form.change', [val]);
}
},
},
methods: {
onInput(value) {
var formatvalue = this.$accounting.unformat(value);
this.$emit("input", formatvalue);
},
onBlur() {
this.focused = false;
this.$emit("blur");
this.dispatch("ElFormItem", "el.form.blur", [this.value]);
},
selectAll(event) {
this.focused = true;
setTimeout(function () {
event.target.select()
}, 0)
},
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root;
var name = parent.$options.componentName;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
}
}
});
二、使用vue/cli脚手架搭建
currencyInput/CurrencyInput.vue
<template>
<div>
<div class="el-input el-input--small" v-bind:class="{'is-disabled':disabled}">
<input class="el-input__inner" v-bind:value="formatValue" v-on:input="updatevalue($event.target.value)" v-on:blur="onBlur" v-on:focus="selectAll" v-bind:disabled="disabled" />
</div>
</div>
</template>
<script>
import accounting from "accounting";
export default {
props: {
value: {
type: [String, Number],
default: 0,
desc: "数值",
},
symbol: {
type: String,
default: "",
desc: "货币标识符",
},
decimal: {
type: Number,
default: 2,
desc: "小数位",
},
disabled: {
type: Boolean,
default: false,
desc: "是否禁止",
},
},
data() {
return {
focused: false,
};
},
computed: {
formatValue() {
if (this.focused) {
return this.value ? accounting.unformat(this.value) : "";
} else {
if (this.value === 0) {
return accounting.formatMoney(this.value, this.symbol, this.decimal);
} else if (
this.value === "" ||
this.value === null ||
this.value === undefined
) {
return "";
} else {
return accounting.formatMoney(this.value, this.symbol, this.decimal);
}
}
},
},
watch: {
value(val) {if (this.validateEvent) {
this.dispatch("ElFormItem", "el.form.change", [val]);
}
},
},
methods: {
updatevalue(value) {
var formatvalue = !!value ? accounting.unformat(value) : "";
this.$emit("input", formatvalue);
},
onBlur() {
this.focused = false;
this.$emit("blur");
this.dispatch("ElFormItem", "el.form.blur", [this.value]);
},
selectAll(event) {
this.focused = true;
setTimeout(() => {
event.target.select();
}, 0);
},
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root;
var name = parent.$options.componentName;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
},
};
</script>
currencyInput/index.js
import currencyInputComponent from "./CurrencyInput"; const currencyInput = { install:function(Vue){ Vue.component("currency-input",currencyInputComponent) } } export default currencyInput
main.js
// 自定义金额格式化组件,并全局注册 import currencyInput from "./components/CurrencyInput"; Vue.use(currencyInput) import accounting from 'accounting'
使用方法
<currency-input v-model="bhform.regCaptial"></currency-input>
三、封装成公共组件:
<template>
<el-input
v-model="displayValue"
@blur="handleBlur"
@focus="handleFocus"
:placeholder="placeholder">
</el-input>
</template>
<script>
export default {
name: 'FormattedInput',
props: {
value: {
type: [String, Number],
default: '',
},
placeholder: {
type: String,
default: '请输入金额',
},
},
data() {
return {
// 内部存储的格式化显示值
displayValue: '',
};
},
watch: {
// 监听父组件传递的 value 变化,更新显示值
value(newVal) {
console.log(newVal);
this.updateDisplayValue(newVal);
},
},
mounted() {
// 初始化时根据父组件传递的 value 更新显示值
this.updateDisplayValue(this.value);
},
methods: {
// 更新显示值,并确保显示值为格式化后的金额
updateDisplayValue(value) {
if (value === '' || value === null || value === undefined) {
this.displayValue = '';
return;
}
// 将值转换为数字
const num = parseFloat(value);
if (!isNaN(num)) {
// 保留两位小数并添加千分位逗号
this.displayValue = num.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
} else {
this.displayValue = '';
}
},
// 失去焦点时格式化金额
handleBlur() {
// 移除所有非数字字符(除了小数点)
let value = this.displayValue.replace(/[^0-9.]/g, '');
// 确保只有一个小数点
const parts = value.split('.');
if (parts.length > 2) {
value = parts[0] + '.' + parts.slice(1).join('');
}
// 转换为数字
const num = parseFloat(value);
if (!isNaN(num)) {
// 保留两位小数
const fixedNum = Math.round(num * 100) / 100;
// 更新显示值为格式化后的金额
this.displayValue = fixedNum.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
// 触发 input 事件,通知父组件值变化,传递纯净值
this.$emit('input', fixedNum.toString());
} else {
// 如果输入无效,清空显示值
this.displayValue = '';
this.$emit('input', '');
}
},
// 获得焦点时移除格式化,方便编辑
handleFocus() {
// 如果有千分位逗号,移除后便于编辑
if (this.displayValue.includes(',')) {
this.displayValue = this.displayValue.replace(/,/g, '');
}
},
},
};
</script>
<style scoped>
/* 样式可根据需要自定义 */
</style>
自定义组件的使用,在父组件中使用:
<template>
<el-form ref="form" :model="formData" label-width="120px">
<el-form-item label="金额" prop="amount" :rules="[{ required: true, message: '请输入金额', trigger: 'blur' }]">
<formatted-input
v-model="formData.amount"
placeholder="请输入金额">
</formatted-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm">提交{{ formData.amount }}</el-button>
</el-form-item>
</el-form>
</template>
<script>
import FormattedInput from './FormattedInput.vue';
export default {
components: {
FormattedInput,
},
data() {
return {
formData: {
amount: '12122', // 父组件接收到的是纯净的金额值
},
};
},
methods: {
submitForm() {
// 直接使用 formData.amount,它已经是纯净的数字字符串
// 如果需要数值类型,可以转换为 Number
const amount = parseFloat(this.formData.amount);
this.$message({
message: `提交的金额为:${amount}`,
type: 'success',
});
// 示例:实际提交逻辑
this.$refs.form.validate(valid => {
if (valid) {
// 提交 amount 到服务器
console.log('提交的金额:', amount);
// 例如:
// axios.post('/api/submit', { amount: amount })
} else {
console.log('表单验证失败');
return false;
}
});
},
},
};
</script>
<style scoped>
/* 样式可根据需要自定义 */
</style>

浙公网安备 33010602011771号