Kodokon kodokon.com

高级表单与原生校验

利用 required、pattern、inputmode 和约束校验 API,无需任何外部库即可构建健壮的表单。

10 分钟 · 3 题

在 Kodokon 中打开本课

浏览器自带一套完整的校验引擎,很多团队却习惯性地用 JavaScript 重新实现它。构建模块有:required(必填字段)、能校验格式的类型(emailurldate)、minlength/maxlength、用于数值的 min/max/step,以及接受正则表达式的 pattern。关键细节:pattern隐式锚定的——整个值都必须匹配,就好像正则被包裹在 ^$ 之间一样。再用标准化的值给字段加上 autocompletepostal-codeemailtel):这既是用户体验,也是无障碍。

HTML
<label for="zip">Postal code</label>
<input id="zip" name="zip" type="text"
       required pattern="[0-9]{5}"
       inputmode="numeric"
       autocomplete="postal-code">
原生校验:格式、必填、匹配的键盘

inputmode 属性常常被误解:它什么都不校验。它只是告诉移动系统显示哪种虚拟键盘(numerictelemaildecimalsearch)。这就是为什么 type="text" + inputmode="numeric" + pattern 的组合是数字编码的推荐做法:你获得了正确的键盘,却不必继承 type="number" 的种种行为。

CSS
input:user-invalid {
  border: 2px solid #b3261e;
}
input:user-valid {
  border: 2px solid #1b5e20;
}
:user-invalid 只有在用户交互后才生效

在 CSS 这一侧,优先选用 :user-invalid 而非 :invalid:后者在页面加载时就立即应用,会把用户还没碰过的字段涂成红色。在 JavaScript 这一侧,约束校验 API 补全了整套工具:checkValidity() 触发检查,validity 对象暴露确切的原因(patternMismatchvalueMissingtooShort),而 setCustomValidity() 让你用自己的消息替换浏览器的通用提示。

JAVASCRIPT
const zip = document.querySelector("#zip");
zip.addEventListener("input", () => {
  if (zip.validity.patternMismatch) {
    zip.setCustomValidity("Enter 5 digits.");
  } else {
    zip.setCustomValidity("");
  }
});
通过校验 API 自定义消息

知识检测

确认你已牢记本课的重点内容。

  1. inputmode="numeric" 到底做了什么?
    • 拒绝任何非数字输入
    • 把字段的值转换成数字
    • 在移动端建议使用数字键盘,但不做任何校验
  2. 使用 pattern="[0-9]{5}",值 "abc12345" 会被接受吗?
    • 会,因为它确实包含 5 个连续数字
    • 不会,因为 pattern 要求整个值都匹配
    • 会,只要字段不是 required
  3. 为什么在样式化错误时优先选用 :user-invalid 而非 :invalid?
    • :user-invalid 只在用户交互后才应用
    • :invalid 不被最新的浏览器支持
    • :user-invalid 还会校验被禁用的字段