对于数字的输入框,需要有各种限制,逐渐形成一个组件,调用方法示例
<money-input
title="XX金额"
:placeholder="defaultPlaceholder"
:verifyErrMsg="errMsg"
@change="updateMoney"
>
<div slot="verifySuccess">
<div class="profit-tips">
预期收益:<span>¥{{`${profit}`}}</span>
</div>
</div>
</money-input>
updateMoney触发之后,拿到对应的值进行相关处理,包括errMsg。具体moneyInput组件内容为
<template>
<div class="money-wrap section">
<div>{{title}}</div>
<div class="money-field">
<label for="mValue" class="buy-label">¥</label>
<x-input
id="mValue"
type="number"
:placeholder="defaultPlaceholder"
@input="moneyInput"
:class="{'noValue': !hasValue, 'hasValue': hasValue}"
v-model='mValue'
></x-input>
<div class="all-in link" @click="allIn">
<slot name="all-in"></slot>
</div>
</div>
<div class="tips">
<div class="error" v-if="!mValue">{{requiredTip}}</div>
<template v-else>
<div class="error" v-if="!!verifyErrMsg">{{verifyErrMsg}}</div>
<div class="succ-tips" v-else>
<slot name="verifySuccess"></slot>
</div>
</template>
</div>
</div>
</template>
<script>
import { XInput } from 'vux'
export default {
name: 'moneyInput-comp',
props: {
title: String,
requiredTip: String,
verifyErrMsg: String,
allRemain: Number,
placeholder: {
type: String,
default: '建议转入100以上'
},
clearMoney: {
type: Boolean,
default: false
}
},
data () {
return {
mValue: null
}
},
computed: {
defaultPlaceholder () {
// 防止 placeholer 大小突变
return this.hasValue ? '' : this.placeholder
},
hasValue () {
return this.mValue && !isNaN(this.mValue)
}
},
watch: {
clearMoney (value) {
value && (this.mValue = null)
}
},
methods: {
moneyInput (val) {
const oldValue = val
const formattedValue = this.handleNumber(val)
if (String(oldValue) !== formattedValue) {
this.mValue = formattedValue
}
this.mValue = formattedValue
this.$emit('change', this.mValue)
},
handleNumber (value) {
// 输入非法字符时,value为'',event.data可以获取此次输入的字符,但支持性差
value = String(value).replace(/[^.0-9]/g, '')
const reg = /\d+(\.\d{1,2})?/g
const realValue = reg.exec(value)
return realValue
? realValue[0]
: value
},
allIn () {
this.allRemain && (this.mValue = this.allRemain)
this.$emit('change', this.mValue)
}
},
components: {
XInput
}
}
</script>
<style lang="scss">
$size-1: 28px;
/*$size-2: 20px;*/
$size-7: 16px;
@mixin focusSet {
font-size: $size-7;
line-height: 40px;
}
.money-field {
display: flex;
.vux-x-input {
width: 100%;
&:before {
border-top:0;
}
input {
width: 85%;
height: 40px;
border: none;
font-size: $size-1;
color: #000;
line-height: 40px;
&:focus {
outline: none;
}
}
}
.noValue {
input {
font-size: $size-1;
color: #D1D1D1;
-webkit-tap-highlight-color:transparent;
}
input[type="number"]::placeholder{
@include focusSet
&::-webkit-input-placeholder{
@include focusSet
}
&:-moz-placeholder{
@include focusSet
}
&::-moz-placeholder{
@include focusSet
}
&:-ms-input-placeholder{
@include focusSet
}
}
}
.weui-cell {
height: 59px;
padding: 10px 0px 10px 15px;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
appearance: none;
margin: 0;
}
}
</style>
<style lang="scss" scoped>
@import "../styles/custom/variables";
.money-field {
position: relative;
/*padding: 27px 0;*/
padding: 10px 0 12px;
box-shadow: $divid-shadow;
display: flex;
align-items: center;
label {
font-size: $size-9;
color: $grey-dark;
font-size: 28px;
}
}
.all-in {
position: absolute;
right: 0;
top: 42px;
}
.money-wrap {
padding: 20px;
.tips {
padding-top: $size-5;
font-size: $size-5;
min-height: 31px;
.err-tips {
color: $red;
}
.succ-tips span {
color: #F64B1D;
}
}
}
</style>
<style lang='scss'>
.money-field{
.hasValue{
.weui-cell__primary input{
font-size: 28px;
}
}
}
</style>