初衷
封装自定义数字键盘,免去各个页面对数字的正确性校验,基础校验集中在数字键盘组件中即可。
H5中的input type为number,有一个弊病就是不支持负数。需求中有输入负数的情况。
思路
字符串拼接,将用户输入的每一个数字都认为是字符串。
在最后完成输入的时候,进行统一校验。
代码
<!--
* @Description: 封装数字键盘
* @Author: Kyeoni hujr
* @Date: 2020-06-22 16:51:32
* @LastEditors: Kyeoni hujr
* @LastEditTime: 2020-09-16 15:29:07
-->
<template>
<view @tap="handleNumberKeyboardTap">
<slot></slot>
<uni-popup ref="popup" type="bottom" :mask-click="false">
<view class="keyboard">
<view class="keyboard-top-button">
<view @tap.stop="handleCancelTap">取消</view>
<view class="keyboard-top-button-title">{{ title }}</view>
<view @tap.stop="handleConfirmTap">完成</view>
</view>
<view class="keyboard-show-box">
{{ showNumber }}
</view>
<view class="keyboard-main-button">
<view class="keyboard-main-button-left">
<view
class="keyboard-button"
hover-class="button-hover"
v-for="(item, index) in [1,2,3,4,5,6,7,8,9]"
:data-key="item"
:key="index"
@tap.stop="handleButtonClick"
>
{{ item }}
</view>
<view
class="keyboard-button"
hover-class="button-hover"
data-key="00"
@tap.stop="handleButtonClick"
>00</view>
<view
class="keyboard-button"
hover-class="button-hover"
:data-key="0"
@tap.stop="handleButtonClick"
>0</view>
<view
:class="['keyboard-button', isInteger && 'integer']"
hover-class="button-hover"
data-key="."
@tap.stop="handleButtonClick"
>.</view>
</view>
<view class="keyboard-main-button-right">
<view
class="keyboard-button-right"
hover-class="button-hover"
data-key="删除"
@tap.stop="handleButtonClick"
>删除</view>
<view
class="keyboard-button-right"
hover-class="button-hover"
data-key="-"
@tap.stop="handleButtonClick"
>-</view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
model: {
prop: 'number',
event: 'change'
},
props: {
number: String,
title: String,
disabled: {
type: Boolean,
default: false
},
isInteger: {
type: Boolean,
default: false
}
},
data() {
return {
show: false,
showNumber: this.number
}
},
watch: {
show (val) {
if (val) {
this.$refs.popup.open()
} else {
this.$refs.popup.close()
}
},
number (val) {
this.showNumber = val
}
},
methods: {
handleNumberKeyboardTap () {
if (!this.disabled) {
this.show = true
this.showNumber = this.number
this.$emit('open')
}
},
handleButtonClick (e) {
let num = this.showNumber
let inputValue = e.currentTarget.dataset.key
if (inputValue === '.' && this.isInteger) {
return
}
if (inputValue === '删除') {
num = num.substring(0, num.length - 1)
} else {
num = num + inputValue
}
this.showNumber = num
},
handleTopClick () {
this.show = false
},
handleConfirmTap () {
if (isNaN(Number(this.showNumber))) {
this.$toast.showCommonToast('请输入格式正确的数字')
return
}
this.$emit('change', this.showNumber = Number(this.showNumber) + '')
this.show = false
},
handleCancelTap () {
this.$emit('close')
this.show = false
}
},
}
</script>
<style lang="scss" scoped>
.keyboard {
background-color: $cyber-border-color;
font-size: 18px;
border-top: 1px solid $cyber-border-color;
font-family: -apple-system;
color: #323233;
.keyboard-top-button {
height: 45px;
line-height: 45px;
color: $cyber-color-primary;
display: flex;
justify-content: space-between;
background-color: #fff;
view {
width: 15%;
padding: 0 20px;
text-align: center;
}
&-title {
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.keyboard-show-box {
height: 50px;
line-height: 50px;
font-size: 20px;
font-weight: 500;
text-align: center;
padding: 10px;
letter-spacing: 1px;
background-color: #fff;
border-top: 1px solid $cyber-border-color;
}
.keyboard-main-button {
padding: 0 10px 10px 10px;
display: flex;
text-align: center;
&-left {
width: 82%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
&-right {
width: 18%;
display: flex;
flex-direction: column;
.keyboard-button-right {
flex: 1;
vertical-align: middle;
color: #666;
background-color: #fff;
margin-top: 10px;
box-shadow: 0 5px 5px 0 #ccc;
font-weight: 500;
border-radius: 5px;
line-height: 100px;
}
}
.keyboard-button {
width: 30%;
color: #666;
background-color: #fff;
height: 50px;
line-height: 50px;
border-radius: 5px;
margin-top: 10px;
box-shadow: 0 5px 5px 0 #ccc;
font-weight: 500;
}
.integer {
visibility: hidden;
}
}
}
.button-hover {
background-color: $cyber-border-color !important;
}
</style>
收获
最大的收获就是最后的数字格式校验。
开发的时候思维定势,一直想的都是用正则进行校验,绞尽脑汁想正则怎么写,兼容正数负数,如果用户输入前导0,怎么把0去掉,等等。
后来经高人提醒,可以直接用类型转换,将字符串转换成数字,转换成功就是数字,转换不成功就是格式有误的字符串。
本文使用 mdnice 排版