最初是想要在H5页面中输入数字的时候调起数字键盘,且只能输入数字和小数点,并且小数点后最多保留两位小数
实践证明:
1.input:
type = 'number'时, 当输入的为非法数字 例如包括-+等,则在取value的值时判断为非数字就会将value自动置为‘’,
且在ios中number类型不能成功调起数字键盘,需要使用pattern调取数字键盘,但是此时系统键盘没有小数点
type = 'tel' 调起数字键盘 没有number value为空的问题
同样在ios没有小数点
type = "text" pattern="[0-9]*" 在安卓无法调取数字键盘 ,在ios能调起数字键盘没有小数点,同时能输入-+/
其他type 则能输入字符等
2.ios原生的可以设置keyboard type = decimal pad . 这个样子的只能用原生.
3.无法实现与web端一致的实时校验 keydown + keyup == input H5只有input
4.前端自己定制键盘,存在安全性问题 且需要禁止系统键盘,并且使用disabled禁止之后 没有光标了也是一个问题
最终解决,在input的时候做校验,但不是实时校验,因为输入字符串的时候编辑完一串字符串点击字符串才会触发input,其实在pc端输入中文也是如此:
<input type="text" class="numberInp" :placeholder="placeholder"
v-model.trim="inputNum" @input="saveNumberData" maxlength="20">
methods:
saveNumberData () {
this.checkFloatNumber(this.inputNum);
}
checkFloatNumber (val){
let reg = new RegExp(/^[0-9]+(.[0-9]{1,2})?$/);
let length_1 = val.length-1;
let length_2 = val.length-2;
if (val) { // 当输入了值
if (!reg.test(val)) { // 并且值不合法
if (reg.test(val.substr(0,length_1))) { // 如果除去最后一位前面的合法
if(val.charAt(length_1) == '.' && val.indexOf('.') == length_1) {
// 当最后一位为小数点并且值中只有一个小数点,则保留值
this.inputNum = val;
} else {
// 否则去掉最后一位
this.inputNum = val.substr(0,length_1);
}
// 如果除去最后两位前面的合法并且最后两位都是小数点,就去掉最后一位
} else if (reg.test(val.substr(0,length_2)) && val.charAt(length_1) == '.' && val.indexOf('.') == length_2) {
this.inputNum = val.substr(0,length_1);
// 否则
} else {
// 如果值只有一位且是小数点,或者值有两位且是‘0.’,则把值置为‘0.’
if(val == '.' || val.substr(0,length_1) == '0.'){
this.inputNum = '0.';
} else {
// 否则提示并清空
let instance = Toast('请输入正确的数值');
setTimeout(() => {
instance.close();
this.inputNum = '';
}, 2000);
}
}
} else {
// 值合法的时候
// 如果第一位为0且第二位存在且第二位不是小数点,提示并清空值
if(val.charAt(0) == 0 && val.charAt(1) && val.charAt(1) !== '.'){
let instance = Toast('请输入正确的数值');
setTimeout(() => {
instance.close();
this.inputNum = '';
}, 2000);
} else {
// 否则保留值
this.inputNum = val;
}
}
}
}
下面是在研究过程中改造的自定义键盘组件:
<template>
<div class="pay-box" v-show="ifShowKB">
<div>
<!--keyboard-->
<transition name="slide">
<div class="key-box">
<div class="item v-1px-t">
<div class="key v-close"
@touchstart="close($event)"
@touchend="inputEnd($event)"
>关闭
</div>
</div>
<div class="item v-1px-t" v-for="(item, i) in keyList" :key="i">
<div class="key"
v-for="(val, key) in item"
:key="key"
@touchstart="inputStart(val, $event)"
@touchend="inputEnd($event)" :class="{'v-1px-l':key!=0}">
{{val}}
</div>
</div>
<div class="item v-1px-t">
<div class="key" style="background: #e8e8e8"
@touchstart="inputStart('.', $event)"
@touchend="inputEnd($event, 'dot')"
>.
</div>
<div class="key v-1px-l"
@touchstart="inputStart(0, $event)"
@touchend="inputEnd($event)"
>0
</div>
<div class="key v-1px-l" style="background: #e8e8e8"
@touchstart="del($event)"
@touchend="inputEnd($event,'del')"
>-
</div>
</div>
</div>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'vue-num-keyboard',
props: {
highlightColor: {// 高亮颜色
type: String,
default: '#ccc'
},
maxLength: { // 最大长度
type: Number,
default: 20
},
ifShow: {
type: Boolean,
default: false
}
},
data () {
return {
val: [],
keyList: [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
}
},
computed: {
ifShowKB () {
return this.ifShow;
}
},
methods: {
inputEnd (e, d) {
this.unhighLight(e.currentTarget, d)
},
// 恢复默认
unhighLight (ele, d) {
if (d) {
ele.style.backgroundColor = '#e8e8e8'
} else {
ele.style.backgroundColor = '#fff'
}
},
// 高亮
highlight (ele) {
ele.style.backgroundColor = this.highlightColor
},
// 用户输入
inputStart (val, e) {
console.log(val, '输入的值----------')
if (this.val.length <= this.maxLength) {
this.val.push(val);
console.log(this.val, '所有的值----------')
} else {
console.log(this.val, '最长----------')
}
this.$emit('numEnd', this.val.join(''));
// 设置高亮
this.highlight(e.currentTarget)
},
del () {
if (this.val.length > 0) {
this.val.pop()
}
this.$emit('numEnd', this.val.join(''));
},
close () {
this.$emit('hideKb');
}
}
}
</script>
<style lang='scss' rel="stylesheet/scss" type="text/css" scoped>
$keyH: .5rem;
$size: .18rem;
.pay-box {
box-sizing: border-box;
z-index: 500;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 5*$keyH;
overflow-x: hidden;
overflow-y: hidden;
background-color: rgba(0, 0, 0, .5);
> div {
position: absolute;
width: 100%;
height: 5*$keyH;
left: 0;
bottom: 0;
background-color: #fff;
}
}
.v-1px-t, .v-1px-l, .v-1px {
position: relative;
}
.v-1px-t:before {
z-index: 112;
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
content: '';
border-top: 1px solid #c7c7c7;
transform: scaleY(.5);
color: #c7c7c7;
transform-origin: 0 0;
}
.v-1px-l:before {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 1px;
content: '';
border-left: 1px solid #c7c7c7;
transform: scaleX(.5);
color: #c7c7c7;
transform-origin: 0 0;
}
.v-1px:before {
position: absolute;
left: 0;
top: 0;
width: 200%;
height: 200%;
content: '';
border: 1px solid #c7c7c7;
transform: scale(.5);
color: #c7c7c7;
transform-origin: left top;
}
/*键盘盒子*/
.key-box {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
font-size: $size;
color: #363636;
.item {
display: flex;
text-align: center;
line-height: $keyH;
height: $keyH;
}
.key {
cursor: pointer;
width: 100%;
height: 100%;
flex: 1;
}
.v-close {
text-align: right;
color: #4a90e2;
}
}
</style>