问题描述
问题1:从数字中间输入会导致输完一个数字之后光标立马跑到input最右端
问题2:添加的空格被视为非光标输入,光标的位置会自动前移一位
例:输入“12345”,input里的内容变为“1234 5”,光标的位置会在5的前面,而不是5的后面
iOS:从头到尾输入时表现正常,问题1会出现,问题2不会出现
Android:有一个Android 7版本的小米手机,在手机自带浏览器中问题2不会出现,但是会出现问题1;其余Android在手机自带浏览器中会出现问题2,没有问题1,在App中只有问题1,没有问题2
猜测
iOS系统和Android系统处理input输入的方式可能不一样,iOS只以内容为主,至于实际是不是键盘输入的并不关心。所以当我们取出输入的内容,并且在中间加了空格,再放回去,input收到的是整个值,不管光标在输入的时候在什么位置,处理完毕之后光标都会被放到最右端。
而Android系统处理input主要以实际输入操作为准,在触发事件中增加了input内容的长度,没有被光标捕获,因此加了空格后光标没有移位,中间插入光标也不会跑到最右端。
解决
-
猜测会不会跟replace函数或者正则表达式有关系,尝试用字符串方法替代replace和正则,但是发现,只要是将格式化后的字符串整个传给input,光标就会跑到最右端
val.replace(/(\d{4})/g, '$1 ') -
值替换一定会修改光标位置,那就尝试直接操作光标吧。
inout.selectionStart和input.selectionEnd原本是用于获取光标所覆盖选区的起始位置和结束位置,若二者相等,则为光标的位置。
对于问题1,我们只需要记录光标在输入时的实时位置,并且在格式化input值之后重新设置光标位置。
对于问题2,我们需要判断当前输入字符串是否会进行添加空格的操作,如果有,则要将光标后移移位,如果没有,则保持不变。change() { ... pos = isNaN(temp) || target.selectionStart % 5 != 0 || val.length < old.length ? target.selectionStart : target.selectionStart + 1; ... } this.$nextTick(() => { ... this.$refs.input.setSelectionRange(pos, pos); ... });
此时iOS系统已恢复正常,但是在输入中文的过程中会有问题。因为iOS在输入中文时,拼音会直接显示到input框内,会触发change事件,且光标是选中状态,选中正在输入的一段拼音。此时修改光标选取会造成输入不正确。修改光标位置记录如下:
let pos = 0;
change() {
...
if (target.selectionStart == target.selectionEnd) {
pos = isNaN(temp) ||
target.selectionStart % 5 != 0 ||
val.length < old.length ?
target.selectionStart : target.selectionStart + 1;
} else {
pos = -1;
}
...
}
this.$nextTick(() => {
...
if (pos != -1) {
this.$refs.input.setSelectionRange(pos, pos);
}
...
});
此时iOS输入已经正常,但是在Android系统下,输入完成后光标位置并未出现变化。猜测浏览器可能有改变光标位置的默认的行为,考虑用定时器setTimeout来改变其在队列中的顺序。
this.$nextTick(() => {
...
if (pos != -1) {
setTimeout(() => {
this.$refs.input.setSelectionRange(pos, pos);
}, 0);
}
...
});
此时两个问题在Android 和 iOS中均得到解决。但是在复制剪切等一下操作上可能还会出现问题。
我想最好的解决方法应该并不是手动控制光标的位置,只是这个方案能解决目前的问题。
针对在iOS和Android设备中输入银行卡号时遇到的光标位置问题,本文详细描述了问题的现象,分析了iOS和Android系统的不同处理方式,并提出了解决方案。解决方案包括记录光标位置、判断是否添加空格以及处理中文输入和剪切复制操作时的光标移动。通过调整光标位置,成功解决了在不同系统和浏览器中输入时的问题。

917

被折叠的 条评论
为什么被折叠?



