前端 BUG 录 - input 数字校验异常问题


思否
前端BUG录 调试 表单 Vue

转载自 SegmentFault

前两天才分享了 input 的属性、特征。昨天就有个小伙伴踩雷了。所以素材又有了

小伙伴做的是实名认证(移动端)相关的功能,然后有个位置校验了只能输入数字。 小伙伴发出了灵魂质疑:为什么 1. 没事 1.. 就被清空了? 这个问题告诉我们喝一点没事,“一點點”不行。

复现代码

功能是基于 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" 这个方案也不行,因为会导致键盘被替换。
  • 自己实现一个键盘

微信公众号:前端linong


原文:SegmentFault

评论

评论功能即将开放。你也可以通过 邮件GitHub Issue 反馈。