创建 web 表单始终是一个复杂的任务。仅仅组装表单是容易的,但是检查每一个字段的值是否有效并且一致是一件更加困难的事情,而如何告知用户错误所在可能会令人头痛。HTML5 引入了表单相关的一些新机制:它为 {{ HTMLElement("input") }} 元素和约束验证增加了一些新的语义类型,使得客户端检查表单内容变得容易。基本上,通过设置一些新的属性,常用的约束条件可以无需 JavaScript 代码而检测到;对于更复杂的约束条件的校验可以尝试使用约束验证 API。
对于这些概念的基本介绍和示例,参阅表单数据校验教程一页的介绍。
HTML 约束验证并不能移除服务端验证的需要。尽管无效的表单请求要少得多,但无效的表单请求仍然可能被发送,例如被试图欺骗你的网络应用的坏人发送。因此,你需要始终在服务端验证输入约束,其方式与在客户端所做的一致。
在 HTML 中,有两种方式声明基本的约束:
type
属性选择最合适的语义化的值,比如,选择 email
类型将会自动创建一个约束,用于检查输入的值是否是一个有效的电子邮件地址。type
属性中的固有约束有:
Input 类型 | 约束描述 | 相关违约 |
---|---|---|
<input type="URL"> |
值必须为 URL 现行标准定义的绝对 URL 地址。 | TypeMismatch 约束违反 |
<input type="email"> |
该值必须是一个语法上有效的电子邮件地址,其格式一般为 username@hostname.tld ,但也可以是本地的,如 username@hostname 。 |
TypeMismatch 约束违反 |
对于这两种输入类型,如果设置了 multiple
属性,可以设置几个值,作为一个逗号分隔的列表。如果其中任何一个不满足这里描述的条件,就会触发 TypeMismatch 约束的违反。
请注意,大多数 input 类型没有内在的约束,因为有些类型被禁止在约束验证中使用,或者有一个净化算法将不正确的值转化为正确的默认值。
除了上面描述的 type
属性外,以下属性用于描述基本约束。
约束验证是通过约束验证 API 在单个表单元素上或在表单层面上,通过 {{ HTMLElement("form") }} 元素本身完成。约束验证是通过以下方式完成的:
HTMLInputElement
、HTMLSelectElement
、HTMLButtonElement
、HTMLOutputElement
或 HTMLTextAreaElement
)的 checkValidity()
或 reportValidity()
方法,只对这个元素进行约束评估,允许脚本获得这些信息。checkValidity()
方法返回一个布尔值,表示该元素的值是否通过其约束(这通常是由用户代理在确定哪个 CSS 伪类,{{ Cssxref(":valid") }} 或 {{ Cssxref(":invalid") }} 适用时完成的)。相反,reportValidity()
方法会向用户报告任何约束失败的情况。HTMLFormElement
接口上的 checkValidity()
或 reportValidity()
方法。调用 checkValidity()
也被称为约束的静态验证,调用 reportValidity()
也被称为约束的交互认证。
novalidate
属性,则不发生约束验证交互。HTMLFormElement
接口上调用 submit()
方法并不触发约束条件验证。换句话说,即使表单数据不满足约束条件,该方法也会将其发送到服务器。在提交按钮上调用 click()
方法来代替。使用 JavaScript 和约束验证 API,可以实现更复杂的约束,例如,结合几个字段的约束,或涉及复杂计算的约束。
基本上,这个想法是在某个表单字段事件(比如 onchange)上触发 JavaScript,以计算是否违反约束,然后使用 field.setCustomValidity()
方法来设置验证的结果:一个空字符串意味着满足约束条件,任何其他字符串意味着有一个错误,这个字符串是显示给用户的错误信息。
每个国家的邮政编码都不相同。大多数国家允许有一个可选的国家代码前缀(如德国的 D-
,法国或瑞士的 F-
),还有其他一些国家的邮政编码只有固定的数字;其他国家,如英国,有更复杂的结构,允许在一些特定的位置有字母。
这不是一个全面的邮政编码验证库,而是关键概念的演示。
作为示例,我们会向以下这个简单的表单中添加一段代码来进行约束验证:
以上代码显示了像这样的表单:
{{EmbedLiveSample("包含多个字段的约束:邮政编码验证")}}
首先,我们来写一个函数来检查本身包含的约束:
然后我们把它链接到 {{ HTMLElement("select") }} 的 onchange 事件和 {{ HTMLElement("input") }} 的 oninput 事件。
另一个常见的约束是限制要上传的文件的大小。在文件传输到服务器之前,在客户端检查这个问题需要将约束条件验证 API,特别是 field.setCustomValidity()
方法,与另一个 JavaScript API 结合起来,这里是文件 API。
这里是 HTML 部分:
会显示:
{{EmbedLiveSample("限制所上传文件的大小")}}
JavaScript 代码会读取所选的文件,使用 File.size()
方法来获取其大小,将其与(硬编码的)限制进行比较,如果有违反,则调用约束 API 来通知浏览器。
最终,我们将这个方法链接到一个正确的事件上:
除了设置约束条件外,web 开发者还想控制向用户显示什么信息以及它们的样式。
元素的外观可以通过 CSS 伪类进行控制。
{{cssxref(':required')}} 和 {{cssxref(':optional')}} 伪类允许开发者编写选择器,以匹配有 required
属性或没有该属性的表单元素。
参见 {{cssxref(':placeholder-shown')}}。
{{cssxref(':valid')}} 和 {{cssxref(':invalid')}} 伪类用于表示 <input> 元素,根据输入的类型设置,这些元素的内容分别可以验证和无法验证。这些类允许用户对有效或无效的表单元素进行样式设计,以使其更容易识别格式正确或不正确的元素。
以下一些方法可以控制违反约束条件的文本:
以下元素上的 setCustomValidity(message)
方法:
submit
的 {{HTMLElement("button")}} 元素,或类型为 {{HTMLElement("input/submit", "submit")}} 的 input
元素创建。其他类型的按钮不参与约束验证。ValidityState
接口描述了由上述元素类型的 validity
属性返回的对象。它表示一个输入值可能无效的各种方式。它们共同解释了为什么一个元素的值是无效的,则不能被验证。