用神奇的 form 驗證 API 來優化你的表單驗證

前言

魚頭曾在 『極限版』不摻水,用純 CSS 來實現超颯的表單驗證功能 一文中分享過一個花裏胡哨的 純 CSS 的表單驗證功能 。雖然僅僅依賴 CSS 是沒法知足咱們的平常開發需求的,可是配合着各類原生的 form 驗證 API ,狀況又不同了。html

下面就讓咱們來了解一下 。git

相關的 API

ValidityState

每個原生的表單組件都會有一個用於描述元素的驗證狀態的對象 —— ValidityStategithub

代碼以下:api

帳號:<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>

輸出以下:瀏覽器

具體屬性以下:ui

屬性 可選值 說明
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() 方法設置的錯誤信息。spa

效果以下:code

代碼以下:orm

帳號:<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 ,不然則爲 falsehtm

效果以下:

代碼以下:

帳號:<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/constraint-validation

一個簡單的 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/pen/RwGLaxa 上查看。

魚頭注:Mmmmm,功能卻是挺好的,若是不是原生的組件樣式太醜,不一樣瀏覽器的表現不一致,並且樣式還不能修改,我想用原生 API 開發的人應該會不少。。。搞不懂爲啥 W3C 不暴露出樣式修改的屬性。。。

參考資料

  1. 『極限版』不摻水,用純 CSS 來實現超颯的表單驗證功能
  2. 『真香警告』這33個超級好用的CSS選擇器,你可能見都沒見過。
  3. form-control-infrastructure
  4. ValidityState
  5. HTMLFormElement
  6. Constraint validation API
相關文章
相關標籤/搜索