复现代码
功能是基于 Vue 来实现的。
<input id="define" type="number" placeholder="最多9999"<keyup="inputKeyUp">
下面是 methods 里面的方法
inputKeyUp: function inputKeyUp(a) { var val = document.getElementById('define').value; var limitNum = 9999, limitLen = 4; val = val.replace(/\.+|\s+/g, ''); if (val.length > limitLen) { val = val.substr(0, limitLen); } if (Number(val) > limitNum) { val = limitNum; } if (val == '0') { val = 1; } if (0 < Number(val) && Number(val) <= limitNum) { this.changeBG = 1; } else { this.changeBG = 0; } document.getElementById('define').value = val; }
复现地址:
https://www.lilnong.top/static/html/input-number-validity.html
问题截图
分析问题提取关键信息
- 移动端、只能输入数字。
input
实现输入,有type="number"
。
- 监听
inputKeyUp
,内部获取.value
,经过正则过滤/\.+|\s+/
,长度截取.substr(0, limitLen)
。
- 通过
.value
再赋值回去
那我们一个一个排查
type
改为默认的 text
。
我们会发现 .
的问题得到了解决。
那么为什么 number
不行?而 text
可以?
可以看到我们都测试了 1..
,但是 number
的时候我们获取到的并没有 .
。运用我们前两天学到的知识,把 validationMessage
打出来看看。
https://segmentfault.com/a/1190000037538101
回想一下H5校验的特征是什么? 只获取正确的参数。
因为这个特征导致我们没有获取到内容,然后在后面赋值的时候被清空了。
正则处理&长度截断
长度截断没什么好说的。
那我们来看一下正则/\.+|\s+/
获取到的是点 \.
和空白符 \s
。
感觉 /[^0-9]/
更好
但是里面不会处理数字,所以和清空没有关系
赋值操作
经过测试可以发现,异常的数值是无法赋值的。
问题成因?
因为使用了 type="number"
然后导致异常值直接无法获取,又因为底部有一个赋值,所以导致被清空。
- 不使用
type="number"
。
如果是pc端,那么没啥毛病,如果是移动端。那么type="number"
其实可以调起一个专用的数字键盘
- 动态改
type="number"
这个方案也不行,因为会导致键盘被替换。
- 自己实现一个键盘