小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
TIP 👉 读书不觉已春深,一寸光阴一寸金。-----王贞白《白鹿洞二首·其一》
前言
在我们日常项目开发中,我们经常会遇到一些输入框的操作,比如我们经常跟money打交道,所以封装了这款金额输入框的组件。金额输入框组件
- 数值为128000时,显示为 128,000.00
属性
1. value 金额数值
- 值为数值类型
2. decimal 小数部分位数
-
值为数值类型
-
默认值:2
3. canRound 是否允许四舍五入
-
值为布尔类型
-
默认值: false
由于JS的 tofixed 方法的四舍五入存在精度问题,不建议设为true
4. canNegative 是否允许输入负数
-
值为布尔类型
-
默认值: true
5. suffixText 输入框后缀显示的文字
-
值为字符串
-
默认值:""
6. icon 输入框后缀显示的图标 (suffixText 为空时有效)
-
值为布尔值或字符串(通过字符串则指定图标的名称)
-
默认值:"rmb"
7. disabled 是否不可用
- 值为布尔类型
8. readonly 是否只读
- 值为布尔类型
事件
1. change 值改变事件
- 参数:value 输入的数值(值为数值类型)
示例
<template>
<MoneyInput v-model="moneyValue" @change="handleChange" ></MoneyInput>
</template>
<script>
import MoneyInput from '@/components/pc/moneyInput'
export default {
name: 'CheckboxDemo',
components: {
MoneyInput
},
data () {
return {
moneyValue: 128000
}
},
methods: {
handleChange (val) {
console.log('输入的金额为:', val)
}
}
}
</script>
实现MoneyInput.vue
<template>
<div class="money-input-wrap" :class="{'show-icon': icon}">
<template v-if="readonly">
<span>{{ currentValue | money(currentDecimal) }}</span>
</template>
<template v-else>
<div class="money-input">
<input ref="rawInput" class="money-raw-input"
v-model="currentValue"
@change="handleChange($event)"
maxlength="15"
:disabled="disabled"
:data-canRound="canRound"
:data-canNegative="canNegative">
<div class="money-show" :class="disabled ? 'disabled-input' : ''">{{currentValue | money(currentDecimal)}}</div>
</div>
<div v-if="suffixText || icon" class="money-suffix-wrap">
<span v-if="suffixText" class="money-suffix-text">{{suffixText}}</span>
<Icon v-else class="money-icon" :name="iconName"></Icon>
</div>
</template>
</div>
</template>
<script>
export default {
name: 'MoneyInput',
props: {
// 当前值
value: Number,
// 小数部分位数
decimal: {
type: Number,
default: 2
},
// 是否四舍五入
canRound: {
type: Boolean,
default: false
},
// 是否允许负数
canNegative: {
type: Boolean,
default: true
},
// 后缀文字
suffixText: {
type: String
},
// 是否显示图标
icon: {
type: [Boolean, String],
default: 'rmb'
},
// 是否可用
disabled: {
type: Boolean,
default: false
},
// 是否只读
readonly: {
type: Boolean,
default: false
}
},
data () {
return {
currentValue: this.value,
currentDecimal: this.decimal
}
},
computed: {
iconName () {
if (typeof this.icon === 'string') {
return this.icon
}
return 'rmb'
}
},
watch: {
value (val) {
this.currentValue = val
}
},
methods: {
handleChange (event) {
let val = event.target.value
let numVal = Number(val)
if (val === '' || isNaN(numVal)) {
this.currentValue = null
this.$emit('input', null)
this.$emit('change', null)
} else {
if (!this.canNegative && numVal < 0) { // 不允许为负数
numVal = Math.abs(numVal)
}
if (!this.canRound) { // 不允许四舍五入
let numArray = numVal.toString().split('.')
let intStr = numArray[0] // 整数部分字符串
let decimalStr = numArray.length >= 2 ? numArray[1] : 1 // 小数部分字符串
if (decimalStr.length > this.decimal) {
let newValueStr = intStr + '.' + decimalStr.substr(0, this.decimal)
numVal = Number(newValueStr)
}
} else {
numVal = this.fixDecimal(numVal, this.decimal) // 修正小数点位数
}
this.currentValue = numVal
this.$emit('input', numVal)
this.$emit('change', numVal)
}
},
// 修正小数点位数
fixDecimal (num, decimal) {
let number = parseFloat(num)
if (num !== undefined && num !== null && num !== '' && !isNaN(number)) {
return parseFloat(number.toFixed(decimal))
}
return num
}
}
}
</script>
<style lang="scss" scoped px2rem="false">
$icon-width: 24px;
.money-input-wrap {
display: table;
width: 100%;
height: $form-item-height;
.money-input {
display: table-cell;
position: relative;
width: 100%;
.money-raw-input {
position: absolute;
top: 0;
width: 100%;
border: 1px solid $border-color-base;
vertical-align: middle;
border-radius: 4px;
font-size: 14px;
color: $input-font-color;
opacity: 0;
z-index: 1;
&:disabled {
background-color: $input-disabled-bg-color;
cursor: not-allowed;
}
&:focus {
@include primary-border-color();
opacity: 1;
&+input.money-show {
opacity: 0;
}
}
}
.money-show {
position: absolute;
top: 0;
width: 100%;
height: $form-item-height;
line-height: $form-item-height - 2px;
vertical-align: middle;
padding: 0 5px;
overflow: hidden;
color: $color-text-regular;
background-color: #FFF;
border: 1px solid $border-color-base;
border-radius: 4px;
&.disabled-input {
background-color: $input-disabled-bg-color;
cursor: not-allowed;
}
}
}
.money-suffix-wrap {
display: table-cell;
min-width: 24px;
padding: 0 5px;
height: $form-item-height;
vertical-align: middle;
text-align: center;
color: $color-text-placeholder;
background-color: $bg-color-base;
border: solid 1px $border-color-base;
border-left: 0;
border-radius: 0 4px 4px 0;
.money-suffix-text {
word-break: keep-all;
white-space:nowrap;
}
}
&.show-icon {
.money-raw-input, .money-show {
padding-right: 0;
border-radius: 4px 0 0 4px;
}
}
}
</style>
index.js
/**
* 金额输入框
* @author qinglianshizhe
* @date 2021/10/11
*/
import MoneyInput from './MoneyInput.vue'
export default MoneyInput
感谢评论区大佬的点拨。