如果你想验证表单输入是否有效,比如你想让输入框只接受整数,而不是小数或文字,在 HTML5 中你可以用以下代码轻松实现:

<input type="number" pattern="[0-9]*" />

但是,用户仍然可以输入无效信息:

  1. 在 Firefox 里,你可以输入任何字符:比如“fsielfs”。
  2. 在 Chrome 里,你可以输入一些无效的数字:比如“1..2.2.2”。

输入框会显示为错误状态,但是如果你覆盖了原生样式就不会看到这个效果了。你需要用 :invalid 选择器来定义错误样式:

input[type="number"]:invalid {
	border-color: red;
}

但是对 JavaScript 来说,它几乎是一个黑箱:

  1. 无效输入不会触发 change 事件。
  2. 当输入无效时,value 返回空字符串 。
  3. validity 属性只能告诉你输入是否有效,而不能提供原始输入值。

也就是说,JavaScript 无法知道用户的错误输入,也无法更改它们。为什么会这样?

当你指定 type="number"pattern="[0-9]*" 时,你将表单格式验证的工作交给了浏览器。当输入无效时,浏览器会提醒并要求用户修正。JavaScript 可以检查 e.target.validity 来了解输入是否有效,但无法了解更多细节。HTML 表单验证对屏幕阅读器非常友好,也很易于使用,是 Web 标准的一部分。而 JavaScript 验证则难以做到这一点。

但是如果我们仍然想要用 JavaScript 来验证和过滤输入……

解决方案 1:用 type="text"

这样你就可以捕获所有字符输入了。你可以在 change 事件中验证和修订 e.target.value。这是最简单全能的方法。

缺点便是失去了系统对输入类型的优化。尤其是在移动设备中,会弹出标准键盘,而不是数字键盘。用户的输入步骤会更加繁琐,影响体验。

解决方案 2:监听 input 事件。

change 事件不同,只要用户输入了内容,不管有效无效,都会触发input 事件。你可以检查 e.data 属性存储输入值。

但它也不是万能的。e.data 得到的只是本次输入的字符,你并不知道光标在哪里,所以不能准确得到完整输入。加入用户按了删除键,你不知道他删除了哪里的多少字符。因此这个方法具有很大的局限性,并不是 100% 可靠。

加入你只要对单个输入字符进行逐一检查,而不需要考虑整体有效与否,那么用这种方法是可以的。在一些情况下,你需要保证每次输入后都是有效状态,可以和 change 事件组合使用,保存每个有效状态,一旦遇到无效输入状态,则退回上一个有效状态。但是,很多输入的中间状态可能是无效的,比如电子邮件,这种情况就不能用 input 事件来解决。

注意:不要用 keydownkeyup 事件,因为它们只检测键盘事件,而输入可能是由复制粘贴,语音输入或虚拟键盘实现的,而不会触发这些键盘事件。

总结一下,确实你可以只用 JavaScript 去验证表单输入。但是我并不推荐这样做。以上两种解决方案都有限制,而且不符合 Web 标准的原则。结合 HTML 和 JavaScript 表单验证,效果会更好。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据