4

用神奇的 form 验证 API 来优化你的表单验证

 2 years ago
source link: https://segmentfault.com/a/1190000040262333
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

鱼头曾在 『极限版』不掺水,用纯 CSS 来实现超飒的表单验证功能 一文中分享过一个花里胡哨的 纯 CSS 的表单验证功能 。虽然仅仅依赖 CSS 是无法满足我们的日常开发需求的,但是配合着各种原生的 form 验证 API ,情况又不一样了。

下面就让我们来了解一下 。

相关的 API

ValidityState

每一个原生的表单组件都会有一个用于描述元素的验证状态的对象 —— ValidityState

代码如下:

账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required  id="input-text" />
<script>
  'use strict';
  const inputText = document.querySelector('#input-text');
  inputText.addEventListener('input', event => {
    console.table(inputText.validity);
  });
</script>

输出如下:

具体属性如下:

属性可选值说明valueMissing(只读)true / false当表单元素设置了 required 属性,且 value 为空时则为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 。typeMismatch(只读)true / false当表单元素输入的值与类型不匹配时为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 。patternMismatch(只读)true / false当表单元素输入的值与 pattern 属性的规则不匹配时为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 。tooLong(只读)true / false当表单元素输入的值长度超过 maxlength 属性时 为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 。tooShort(只读)true / false当表单元素输入的值长度少于 minlength 属性时 为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 以及 :in-range / :out-of-range 。rangeUnderflow(只读)true / false当表单元素输入的值少于 min 属性时 为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 以及 :in-range / :out-of-range 。rangeOverflow(只读)true / false当表单元素输入的值大于 max 属性时 为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 以及 :in-range / :out-of-range 。stepMismatch(只读)true / false当表单元素输入的值与 step 的值不匹配 时为 true ,否则为 false 。此属性关联伪类 :valid / :invalid 以及 :in-range / :out-of-range 。badInput(只读)true / false当表单元素输入的值不完整且 UA 认为当前状态的表单不应该被提交时为 true,否则为 false。customError(只读)true / false当表单元素的错误信息是由 setCustomValidity() 方法调用展示时为 true,否则为 false。valid(只读)true / false当表单元素验证通过时为 true ,否则为 false 。此属性关联伪类 :valid / :invalid

validationMessage

当表单元素验证正确时则返回 '',否则则返回默认或者经由setCustomValidity() 方法设置的错误信息。

效果如下:

代码如下:

账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required  id="input-text" />
<script>
    'use strict';
    const inputText = document.querySelector('#input-text');
    inputText.addEventListener('input', event => {
      console.table(inputText.validationMessage); // 验证错误时则返回 “请与所请求的格式保持一致。”
    });
</script>

willValidate

一个只读属性,当表单元素需要验证时返回 true ,否则则为 false

效果如下:

代码如下:

账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required  id="input-text" />
<script>
    'use strict';
    const inputText = document.querySelector('#input-text');
    inputText.addEventListener('input', event => {
      console.table(inputText.willValidate); // true
    });
</script>

setCustomValidity()

setCustomValidity() 用于设置表单元素 validationMessage 的值。当设置 setCustomValidity() 之后,validity.customError 就会变成 true 。如果需要重置,则输入空字符串即可。

我们看看效果图:

代码如下:

<form class="form" id="form" method="get" action="/api/form">
      账号:
    <input id="account" data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required />
    <input id="submit" name="button" type="submit" value="提交" />
</form>

<script>
    'use strict';
    account.setCustomValidity('自定义错误!');
    form.addEventListener('submit', event => {
          event.preventDefault();
    });
</script>

checkValidity()

checkValidity() 用于检查当前表单元素或整个表单的值是否通过验证,如果是则为 true,否则则为 false

效果如下:

代码如下:

账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required  id="input-text" />
<script>
    'use strict';
    const inputText = document.querySelector('#input-text');
    inputText.addEventListener('input', event => {
          console.table(inputText.checkValidity());
    });
</script>

reportValidity()

reportValidity() 用于触发以及检查表单元素的值是否通过验证,如果是则为 true,否则则为 false

效果如下:

代码如下:

账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required  id="input-text" />
<script>
    'use strict';
    const inputText = document.querySelector('#input-text');
    console.log(inputText.reportValidity());
</script>

以上 API 兼容性如下:

图片来自:https://caniuse.com/constrain...

一个简单的 form 提交例子

我们看效果:

代码如下:

<style>
    .form > input {
          margin-bottom: 10px;
    }
</style>
<form class="form" id="form" method="get" action="/api/form">
    账号:
    <input id="account" data-message="请输入正确的账号" data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required />
    <br />
    密码:
    <input id="password" data-message="请输入正确的密码" data-title="密码" placeholder="请输入正确的密码" pattern="\w{6,10}" name="password" type="password" required />
    <br />
    <input id="submit" name="button" type="submit" value="提交" />
</form>
<script>
  'use strict';
  const inputs = [account, password];
  inputs.forEach(input => {
      input.addEventListener('input', () => {
          input.setCustomValidity('');
          input.checkValidity();
      });
      input.addEventListener('invalid', event => {
          const { message } = event.target.dataset;
          const { validity: { valid } } = input;
          input.setCustomValidity('');
          if (!valid) {
                input.setCustomValidity(message);
          };
      });
  });
</script>

以上例子可以在鱼头的 Codepenhttps://codepen.io/krischan77... 上查看。

鱼头注:Mmmmm,功能倒是挺好的,如果不是原生的组件样式太丑,不同浏览器的表现不一致,而且样式还不能修改,我想用原生 API 开发的人应该会很多。。。搞不懂为啥 W3C 不暴露出样式修改的属性。。。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK