HTML5利用約束驗證API來檢查表單的輸入數據

HTML5利用約束驗證API來檢查表單的輸入數據

HTML5對於表單有着極大程度的優化,無論是語義,小部件,還是數據格式的驗證。我猜你肯定會以瀏覽器兼容作爲藉口不願意使用這些“新功能”,但這絕不應該成爲使你停滯不前的原因,況且還有像Modernizr和ployfill這樣的工具庫幫助你在不支持HTML5的瀏覽器上進行回退處理。當你真正試着使用這些表單的新功能時,我保證你會愛上它。如果說唯一的缺陷,就是提示框的樣式是瀏覽器默認的,你無法改變,好吧,如果你相信瀏覽器廠商的設計師的審美水平的話(我相信他們的設計水平比絕大部分普通人要好,如果不考慮風格兼容的話),抓緊學就對了!

這篇文章不會去討論簡單的input type,本文想把重點放在HTML5表單驗證機制上。主要介紹是HTML5是如何利用約束驗證API來檢查表單的輸入數據的,當然,本文會涉及到很多其它的知識。

原生驗證

input type

HTML5中爲數據格式驗證提供了很多原生的支持,例如:

<input type='email'/>

當點擊提交按鈕時,如果你輸入的格式不符合email,則會導致無法提交,瀏覽器會提示你錯誤信息。

比如在chrome下:

注意:

  1. 僅當你提交的時候會觸發瀏覽器的驗證
  2. 不同瀏覽器提示信息的行爲樣式不一樣
  3. 當有多個input不符合要求時,只會提示一個錯誤,一般會提示表單中相對較前的Input的

不要理所應當的認爲當input的type等於tel的時候,如果你輸入的不是電話號碼格式,在提交時也會被瀏覽器的阻擋並提示錯誤信息,type=’tel’在PC端只起到語義的作用,在移動端可以使產生的鍵盤爲純數字鍵盤,並不能起到數據驗證的作用。

pattern

你可以使用pattern屬性來對瀏覽器不提供原生驗證的數據格式設置自定義格式驗證。pattern屬性的值是一個正則表達式(字符串):

<input type='tel' pattern='[0-9]{11}' title='請輸入11位電話號碼'>

點擊提交時,如果你輸入的數據不符合pattern裏面正則的格式,那麼瀏覽器會阻止表單提交,並提示:‘請與所請求的格式保持一致’+ title裏的內容(小字)。但注意,當你的文本框中內容爲空的時候,瀏覽器不會對其進行檢查,會直接提交表單(因爲瀏覽器認爲這個框框不是必填項)。如果你想要這個框框必須有內容,請加上required屬性。

通過HTML原生的驗證系統,基本就能滿足我們對錶單提交的限定。但HTML5提供了更高級的功能來方便我們開發和提升用戶體驗。

約束驗證API

默認提示信息

像‘請與所請求的格式保持一致’這樣的瀏覽器提示信息字串藏在input DOM對象的validationMessage屬性裏,這個屬性在大多數現代的瀏覽器中是隻讀的,即不可修改,比如下面的代碼:

<input type="text" required id='input'/>

當提交時,如果Input內容爲空,那麼瀏覽器會提示‘請填寫此字段’,我們可以在控制檯把這句話打印出來:

var input = document.getElementById('input')
input.validationMessage // =>'請填寫此字段'

如果想修改其中的內容,可以調用setCustomValidity接口改變validationMessage的值

input.setCustomValidity('這個字段必須填上哦');
// 下面這種做法適用於不支持setCustomValidity的瀏覽器,基本現代瀏覽器都不支持這樣做
input.validationMessage = '這個字段必須填上哦'

注意,像required這樣的HTML原生驗證,雖然能改變其中信息,但無法把信息置爲空字串,原因下面會講到。

原理

HTML表單驗證系統通過validationMessage屬性檢測該文本框的數據是否通過驗證,如果其值爲空字串,則表示通過了驗證,否則,表示未通過,瀏覽器會把其值作爲錯誤信息提示給用戶。所以在原生驗證時,用戶無法把validationMessage的值設置爲空字符串。

約束驗證API的簡單實例

約束驗證API是在原生方法之上更靈活的表達方式,你可以自己設置數據是否通過,而不藉助於正則表達式。原理很簡單,通過if判斷,如果數據格式使你滿意,那麼你就調用setCustomValidity使validationMessage的值爲空,否則,你就調用setCustomValidity傳入錯誤信息:

input.addEventListener('input', function () {
        if(this.value.length > 3){ // 判斷條件完全自定義
            input.setCustomValidity('格式不正確');
        }else {
            input.setCustomValidity('')
        }
 });

每次鍵盤輸入,代碼都會判斷格式是否正確,然後調用setCustomValidity設置validationMessage的值。不要妄想每按下鍵瀏覽器都會提示你結果是否正確,瀏覽器只有在點擊提交按鈕的時候纔會提示validationMessage裏的值(如果有的話)

如果你還沒有走思的話,一定會問,既然這樣,爲什麼要爲input綁定鍵盤事件,每輸入一下都要進行判斷呢?直接爲表單綁定提交事件,在提交時再判斷多好,別急,這麼做是有好處的。

隨着輸入判斷格式與樣式

作爲用戶,我們當然想在得知我輸入了錯誤的格式之後,文本框變紅(或者有別的提示)。而在我每次輸入一個字符,如果對了,文本框就恢復正常。我們可以使用CSS僞類來實現這個功能:

    input:required {
            background-color: #FFE14D;
        }

    /*這個僞類通過validationMessage屬性進行判斷*/
    input:invalid {
        border: 2px solid red;
    }

上面的required僞類會給所以必填但值空的input提供一個黃色的背景色,而下面的invalid僞類則會爲所有未通過驗證的input添加一個2px的紅邊邊。我們現在給我們的Input框加上input類即可。

這些僞類的判斷條件正與瀏覽器判斷你能否提交表單的條件一樣,看validationMessage裏的值,所以,我們上面設置每次鍵盤輸入事件都會觸發一次判斷從而改變CSS僞類樣式的渲染,用意正在於此。

更好的用戶體驗

還有一個缺點,就是當一個input設置爲required的時候,在初始化時,因爲其本身是空的,所以invalid僞類會對它起作用,這不是我們想看到的,因爲我們什麼還都沒有幹。

我們可以並在這些僞類前加上父選擇器.invalid,這樣,只有在父元素具有invalid類時,這些僞類纔會起作用。可以設置一個submit事件,在表單提交因驗證失敗後,會觸發input的invalid事件,給form添加invalid類:

form.addEventListener('invalid', function() {this.className = 'invalid'}, true)

因爲invaild是Input的事件,而不是form的事件,所以這裏我們設置第三個參數爲true採用事件捕獲的方式處理之。這樣,就大功告成了。

最終實例

好了,現在是時候總結一下我們所學的知識並創造最佳實踐了:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>form</title>
    <style>
        input:required{
            background-color: #DCD4CE;
        }
        .invalid input:invalid{
            border: 2px solid red;
        }
    </style>
</head>
<body>
<form id="form">
    <label>email:<input type="email" required id="email"></label>
    <label>IDCard:<input required id="IDCard"></label>
    <input type="submit" id="submit">
</form>
<script>
    var email = document.getElementById('email');
    var IDCard = document.getElementById('IDCard');
    var form = document.getElementById('form');

    IDCard.addEventListener('input', function () {
        if(this.value.length != 6) {
            this.setCustomValidity('IDCard的長度必須爲6')
        }else{
            this.setCustomValidity('')
        }
    });

    form.addEventListener('invalid', function () {
        this.className = 'invalid';
    }, true)
</script>
</body>
</html>

運行後截圖如下:

發佈了42 篇原創文章 · 獲贊 67 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章