自定义表单验证

我们知道原生的html元素支持做一些简单的验证,但是不是很美观,我们可以自己来定义这些错误消息,仍然使用元素的那套验证。

validity属性提供了关于表单字段的一组信息,值是布尔值(true/false)。

var myField = document.querySelector('input[type="text"]');
var validityState = myField.validity;

返回的对象(validityState)包含以下属性:

  • valid: 当字段通过验证的时候,是true

  • valueMissing: 当必填的字段是空的时候,这个是true

  • typeMismatch: 当字段type限制是emailurl的时候,但输入的value(值)不是正确的类型,这个时候返回的值是true

  • tooShort: 这个就是当元素有minLength属性的时候,但是输入的value没有达到这个限制(比这个小),这时候是true

  • tooLong: 这个和tooShort差不多,不过这个是和maxLength进行对比。

  • patternMismatch: 这个与typeMismatch差不多,不过是与pattern类型相比较。

  • badInput: 类型是number,但是输入的value不是number,就会返回true

  • stepMismatch: 当字段具有step属性且输入的value不符合步骤值时,返回true

  • rangeOverflow: 当字段具有max属性且输入的数字value大于max时,就返回true

  • rangeUnderflow: 当字段具有min属性且输入的数字value低于min时,就会返回true

下面就用这些验证和js配合,来构建一个健壮的表单验证。

禁用原生验证

首先使用novalidate属性来禁止原生的form验证提示。 作为最佳实践,我们应该使用js脚本来添加,这样当js无法加载时,保证原生的验证仍然可用。

可能有些表单,你不想验证,比如搜索表单。你只想验证一些需要验证的表单,那么我们来加一个类名,叫做. validate

可以在线查看效果。

用户离开时检查有效性(失去焦点)

我们将使用事件冒泡(或事件传播)来监听所有blur事件,而不是为每个表单字段添加一个监听器。

对于上面代码第三个参数(true)不了解的同学可以看看这里

第三个参数叫做useCapture,他通常默认是设置成falseblur事件不会像click事件那样冒泡。将此参数设置为true允许我们捕获所有blur事件,而不仅仅是那些直接发生在我们正在侦听的元素上的事件。

接下来,我们要确保blur元素是具有.validate类的表单中的字段。我们可以使用event.target获取blur的元素,并通过调用event.target.form获取它的父级form。然后使用classList来检查是否含有验证这个类。

如果errortrue,则该字段有效。否则,出现错误。 可以在线查看

获取错误

由于我们需要检查每个属性,因此代码可能会有点长。让我们为此设置一个单独的函数,并将我们的字段传递给它。

我们要忽略一些字段类型:禁用的字段,filereset输入以及submit input和按钮。如果一个字段不是其中之一,那就让它有效。

如果没有错误,我们将返回null。否则,我们将检查每个有效状态属性,直到找到错误。

这是一个好的开始,但我们可以做一些额外的解析,以使我们的一些错误更有用。对于typeMismatch,我们可以检查它是否应该是emailurl,并相应地自定义错误。

如果字段值太长或太短,我们可以找出它应该有多长或多短以及实际有多长或多短。然后我们可以在错误中包含该信息。

如果数字字段超出或低于允许范围,我们可以在错误中包含最小或最大允许值。

如果pattern模式不匹配且字段具有title,我们可以将其用作我们的错误显示,就像浏览器原生行为一样。

这是我们的hasError()函数的完整代码:

在线的codepen中自己尝试一下。

显示错误消息

我们将创建一个showError()函数来处理它,并传入我们的字段和错误。然后,我们将在事件监听器中调用它。

showError中将会做几件事: 1. 我们将在字段中添加一个带有错误的类,以便我们可以设置它的样式。 2. 如果已存在错误消息,我们将使用新文本对其进行更新。 3. 否则,我们将创建一条消息并在字段后立即将其注入DOM。

我们还将使用字段ID为消息创建唯一ID,以便稍后再次找到它(如果没有ID,则使用name)。

为了确保屏幕阅读器和其他辅助技术知道我们的错误消息与我们的字段相关联,我们还需要添加aria-describedby角色。

设置错误消息的样式

我们可以使用.error.error-message类来设置表单字段和错误消息的样式。 举个简单的例子,你可能希望在带有错误的字段周围显示红色边框,并将错误消息设置为红色和斜体。

在线效果

隐藏错误消息

一旦我们显示错误,字段验证后,我们需要删除错误消息。让我们创建另一个函数removeError(),并传入该字段。我们也将从事件监听器调用此函数。

removeError()中,我们想要: 1. 从我们的字段中删除错误类。 2. 从字段中删除aria-describedby角色。 3. 隐藏DOM中的任何可见错误消息。

因为我们可以在页面上有多个表单,并且这些表单可能具有相同名称或ID的字段(即使这些字段无效,也会发生),我们将使用querySelector限制我们对错误消息的搜索,而不是整个文档。

来看看[效果](https://codepen.io/cferdinandi/embed/JJYYpY?height=559&theme-id=1&slug-hash=JJYYpY&default-tab=js%2Cresult&user=cferdinandi&embed-version=2&pen-title=Form Validation%3A Remove the Error After It's Fixed&name=cp_embed_5)。 如果该字段是单选按钮或复选框,我们需要更改我们将错误消息添加到DOM的方式。 对于这些类型的输入,字段标签通常位于字段之后,或者完全包装它。此外,如果单选按钮是组的一部分,我们希望错误出现在组之后,而不仅仅是单选按钮。 看看这里

首先,我们需要修改showError()方法。如果字段typeradio并且它具有name,我们希望获得具有相同name的所有单选按钮(即组中的所有其他单选按钮)并将我们的field变量重置为组中的最后一个。

当我们将消息注入DOM时,我们首先要检查字段类型是否为radiocheckbox。如果是这样,我们希望得到字段标签并在它之后而不是在字段本身之后注入我们的消息。

当我们去除错误时,我们同样需要检查该字段是否是组中一部分的单选按钮,如果是,请使用该组中的最后一个单选按钮来获取错误消息的ID。

那再来看看在线的例子啊

检查提交中的所有字段

submit事件添加一个监听器。

如果表单具有.validate类,我们将获取每个字段,遍历每个字段,并检查错误。

来啊,再来看看在线的现成版本

原文:Form Validation Part 2: The Constraint Validation API (JavaScript)

Last updated