一、抛出问题
在很多业务中需要对输入框进行字符限制,比如金额输入框、手机号码输入框等。
二、解决问题
以下是三种尝试过的解决方案,最后一个自觉最优,如有更优解决方案,望指教。没多少经验的菜鸟们快来围观:
1 次方案
遇到这种问题,在百度上你一般会找到这样的处理:
<input onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')">
但这会出现一个问题:光标定位到某个字符并删除后,输入框的值被重新赋值,光标也跟着去到了字符串末尾。这是个很不好的体验。
2 次方案
这样的结果让我第一个想到的解决办法就是,在键入之前就屏蔽掉非数字,即在keydown(按下,但并没有对输入框赋值)事件中,判断输入的key,如果不是数字则不给输入框赋值:
$("input").keydown(function(e){
//非数字键值
if (e.key && exp.test(e.key) == false && e.key != "Backspace") {
return false;
}
//alert(e.keyCode);
//非数字键值 兼容iPhone6s低版本的机型
if ((e.keyCode >= 48 && e.keyCode <= 57) == false && e.keyCode != 8) {
return false;
}
}
ok,正如代码里所看到的,多了一段兼容代码。由于iphone6s某版本及以下版本 获取到的key为undefined,所以只能通过keyCode判断。而问题又来了,在手机上的键盘,“*”和“8”的keyCode编号是一样的,无法区分,存在小缺陷。
有人针对这个小缺陷提出的弥补方案是:在失去焦点的时候再去掉,T_T,那还不如都在失去焦点的时候处理。。。
3 最佳方案
所以我不甘心,继续尝试,终于找到了一个完美的解决方案:
那就是在键入后纠正并定位到键入前光标的位置,实质地解决了最初问题,请看代码。
$("input").keyup(function(){
var inpVal = $(this).val();
var exp = /^[0-9]*$/;
var focusIndex = this.selectionStart;
if (exp.test(inpVal) == false) {
var rightVal = inpVal.length == 1 ? inpVal.replace(/[^0-9]/g, '') : inpVal.replace(/[^\d]/g, '');
var replaceNum = inpVal.length - rightVal.length;
//纠正为数字字符
$(this).val(rightVal);
//重新设定光标位置
this.selectionEnd = focusIndex - replaceNum;
this.selectionStart = focusIndex - replaceNum;
}
});