开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
背景: 基于element ui开发后台管理,部分输入内容涉及金额输入,用户看到的单位是元,后端接口接收的单位是分,存在一个转化问题
方法一:
特点:element-ui自带组件,需要对结果进行装换,用的地方多,感觉比较麻烦,查询结果显示的时候,需要除以100,给接口的时候需要乘以100
直接使用 inputNumver 计数器
<template>
<div>
<el-form v-model="form">
<el-form-item label="商品名称" prop="name">
<el-input placeholder="请输入商品名称" v-model="form.name" />
</el-form-item>
<el-form-item label="价格" prop="price">
<price-input :form="form" prop="price"></price-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
form: {
name: "",
price: 0,
},
};
},
};
</script>
接口接收的时候,参数需要进行元转化为分处理:
-
直接乘以100,可能会有多为小数的问题。
解决方法:
Vue.prototype.yuanToFen = function (num) {
return parseFloat(Math.round(num * Math.pow(10, 2)) / 1);
}
方法二:
封装组件,希望达到的效果,接收的单位是分,展示的单位元,更改的时候联动:更改元,对应的form数据里分也跟着变动。
组件PriceInput,接收参数 form:当前表单数据,prop: 对应的参数名称。
<price-input :form="form" prop="price"></price-input>
复制代码
- 金额需要支持边界,使用
el-input
- web 页面输入,需要限制输入的是数字,且小数点后最多两位
- 解决方法,自定义指令,对键盘输入内容或粘贴内容进行监听,过滤数据
- 金额转换部分逻辑(核心)
- 接收金额为分,显示金额为元,且不改变form表单内price的单位,则显示金额需要一个新的变量用作展示:
displayValue
- 需要在第一次接收到数据的时候,进行一次转换,赋值给
displayValue
- 监听输入框的
input
事件,输入框内容改变的时候,更新form.price
和displayValue
- 监听输入框的
change
事件,输入框失去焦点的时候,更新form.price
和displayValue
displayValue
依赖于初次数据,和输入数据,因此使用计算属性
监听数据输入的指令代码:
Vue.directive('enterMoney', {
inserted: function (el) {
el.addEventListener('keypress', function (e) {
e = e || window.event
const charcode = typeof e.charcode === 'number' ? e.charcode : e.keyCode
const re = /\d/
if (charcode === 46) {
if (el.children[0].value.includes('.')) {
e.preventDefault()
}
return
} else if (!re.test(String.fromCharCode(charcode)) && charcode && !e.ctrlKey) {
if (e.preventDefault) {
e.preventDefault()
} else {
e.returnValue = false
}
}
else {
// console.log('dir--',el.children[0].value, e.key)
let reg = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/
if (el.children[0].value) {
if (!reg.test(el.children[0].value + e.key)) {
e.preventDefault()
}
}
}
})
}
});
PriceInput.vue 组件:
<template>
<div>
<el-input
v-enter-money
:value="displayValue"
:placeholder="placeholder"
:disabled="disabled"
@input="handleInput"
@change="handleInputChange"
>
</el-input>
</div>
</template>
<script>
export default {
name: "PriceInput",
props: {
/* 初始价格 */
form: {
type: Object,
default: function () {
return {};
},
},
disabled: {
type: Boolean,
default: false,
},
prop: {
type: String,
default: "",
},
placeholder: {
type: String,
default: "",
},
},
data() {
return {
currentValue: 0,
userInput: null,
};
},
watch: {
form: {
handler(val) {
if (val) {
let num = this.form[this.prop];
if (num != undefined && num != null) {
this.userInput = num / 100;
this.currentValue = this.userInput;
} else {
this.userInput = null;
this.currentValue = null;
this.$set(this.form, this.prop, null);
}
}
},
immediate: true,
// deep:true
},
},
computed: {
displayValue() {
if (this.userInput !== null) {
this.changeValue(this.userInput);
return this.userInput;
}
let currentValue = this.currentValue;
this.changeValue(currentValue);
return currentValue;
},
},
methods: {
changeValue(val) {
if (val != null && val != "") {
this.form[this.prop] = parseFloat(
Math.round(val * Math.pow(10, 2)) / 1
);
} else {
this.form[this.prop] = null;
}
},
handleInput(value) {
this.userInput = value;
},
handleInputChange(value) {
const newVal = Number(value);
if (!isNaN(newVal) && value != "") {
this.currentValue = parseFloat(
Math.round(newVal * Math.pow(10, 2)) / Math.pow(10, 2)
);
} else {
this.currentValue = null;
}
this.userInput = null;
},
},
};
</script>