最近在公司做一个项目,简单来说就是web端微信公众号上的一个申请表单页面,随便如个图
环境: vue框架 + vant组件库 + 其它(这里用不上的,不说)
具体如图:
都知道,input输入框如果不去给它设置属性,它默认地在移动端访问时,获取焦点的时候弹出的是中文,或者英文之类的默认键盘,反正不是数字键盘,但是看图可知,有关数量或者电话之类的数字字符串输入,并不需要中文或者英文字母,只需要输入数字即可,这个时候如果使用数字键盘,就能有效的避免用户输入其它不必要的字符串
场景是这样的…
既然需要使用数字键盘,而vant组件库恰好有这个组件,第一时间想到的肯定是使用vant组件库自带的数字键盘,文档链接:vant组件库数字键盘
部分代码:(代码较多,粘贴部分,能达到效果就行)
页面展示部分:
......
定义数据:
data() {
return {
hospitalInfo: {
bedNum: '', // 编制床位数
bedOpen: '', // 开放床位数
......
},
keyShow: false, // 控制数字键盘显示/隐藏
diffType: 'bedNum', // 区分点击弹出数字键盘的是哪一行
......
};
}
添加数字键盘组件
输入框点击事件:
// 点击编制床位数一栏
bedNumKeyboardUp() {
this.keyShow = true;
this.diffType = 'bedNum'; // 用于区分点击的是呢个输入框,下面会用到
},
// 点击开放床位数一栏
bedOpenKeyboardUp() {
this.keyShow = true;
this.diffType = 'bedOpen';
},
数字键盘绑定事件:
// 数字键盘 点击按键时触发
onInput(value) {
this.hospitalInfo[this.diffType] = `${this.hospitalInfo[this.diffType]}${value}`; // 将点击的那个按键的值(value)加到输入框中已有的字符串最后
},
// 数字键盘 点击删除键时触发
onDelete() {
const value = this.hospitalInfo[this.diffType].toString();
if (Number(value.slice(0, value.length - 1)) === 0) {
this.hospitalInfo[this.diffType] = '';
} else {
this.hospitalInfo[this.diffType] = Number(value.slice(0, value.length - 1));
}
},
注:Number('') = 0
这样做,这个数字键盘就能用,PC端,Android端,iOS12上,都能正常使用,除了在iOS10系统上,万恶的iOS系统…
问题描述:
使用vant组件库数字键盘,在PC端,Android手机上,iOS12手机上(只知道iOS12,其它的暂时不知道),无论是本地测试,还是发布上线,都没问题。
但是iOS10是个意外,使用iOS10手机在本地测试没问题,但是等把代码发布上线,在用iOS10手机访问,就会出现以下妖魔鬼怪的现象:在iOS10系统的手机上访问线上的页面,点击数字键盘任意键,键盘都会异常收起,有时候还会出现键位错位的情况
当时的解决思路
思路一:
既然是每次点击数字键盘任意键异常收起键盘,那就给点击按键时触发的onInput
函数一个this.keyShow = true;
,每次点击任意按键,都让数字键盘显示
onInput(value) {
this.keyShow = true; // 数字键盘显示
this.hospitalInfo[this.diffType] = `${this.hospitalInfo[this.diffType]}${value}`;
},
这样做最开始能达到效果,但是后来不知道咋个回事,他又不行了
思路二:
去vant组件库的GitHub上的lssues中找找有没有这个问题,还真找了个差不多的,但是照他的方法做,也没有解决,留个链接供参考,
链接:自己参考
最终解决方案
在网上找了很久,看了很多文章,都没有一个有用的方法,最后还是经大佬提点,决定自己封装一个自定义的数字键盘组件
网上一搜,基于vue封装自定义数字键盘的文章一大堆,我是借鉴的这位大佬的文章:Vue自定义数字键盘组件
在他的基础上,进行了部分的修改,改成了适合本次项目所需要的样子,如图
自定义数字键盘代码:
=> components/NumKeypad.vue
--------------
7
8
9
4
5
6
1
2
3
.
0
删除
清空
确认
父组件使用上面的自定义组件:
导入:import Calculation from '~/NumKeypad';
// 上面写的那个组件的路径,这个‘~’是自己设置的路径别名
注册:
components: {
Calculation,
},
......
定义数据:
data() {
return {
hospitalInfo: {
bedNum: '', // 编制床位数
bedOpen: '', // 开放床位数
......
},
keyShow: false, // 控制数字键盘显示/隐藏
diffType: 'bedNum', // 区分点击弹出数字键盘的是哪一行
......
};
}
// 点击编制床位数一栏,弹出数字键盘
bedNumKeyboardUp() {
console.log('弹出编制床位数数字键盘');
this.keyShow = false;
setTimeout(() => { this.keyShow = true; }, 100);
this.diffType = 'bedNum';
},
// 点击开放床位数一栏,弹出数字键盘
bedOpenKeyboardUp() {
console.log('弹出开放床位数数字键盘');
this.keyShow = false;
setTimeout(() => { this.keyShow = true; }, 100);
this.diffType = 'bedOpen';
},
为啥先false了又true?
由于使用数字键盘的输入框都设置了只读属性,目的是为了在点击时不使输入框获取焦点,因为获取焦点会弹出系统自带的默认键盘,既然现在无法获取焦点了,点击输入框时就不会有那个竖杠杠(获取焦点时输入框中的那个),这里如果只设置显示数字键盘(this.keyShow = true;),点击一个输入框显示出数字键盘后,再点击其它输入框,键盘不会有任何行为,即一直显示在那里,这就导致给用户一种错误的反馈,感觉好像点击其它输入框没点到似的.
这两排代码的作用就是,当个点击输入框时,会有个键盘收起后紧接着弹出的过程,就能给用户一种切换输入框成功了的感觉,不过我觉得这个方法很挫,肯定还有更好的方法来解决这个问题,以后想起了再记得来加上
// 点击数字键
numberEvent(res) {
// console.log('数字键:', res);
this.hospitalInfo[this.diffType] = `${this.hospitalInfo[this.diffType]}${res}`;
},
// 点击清除键
clearEvent(res) {
// console.log('清除键:', res);
this.hospitalInfo[this.diffType] = res; // 清除,子组件传过来的是‘’
},
// 点击删除键
deleteEvent(res) {
// console.log('删除键:', res);
this.hospitalInfo[this.diffType] = res;
},
// 点击确认键
confirmEvent(res) {
console.log('确认键:', res);
this.keyShow = false; // 点击确认,收起键盘
},
this.keyShow = false;
用到了的一些知识点:
vue中传值,父传子,子传父,此处都有用到,不明白参考连接:vue传值方式
data-* 属性, 参考链接:data-* 属性
substring()方法:substring()方法
记录一下,以后如果还有vue+vant的web项目,如果有用到数字键盘时,直接用这个自定义的数字键盘,不使用vant自带的那个,在iOS10上就不会再有那个问题了