html5 数据验证,【译】表单数据校验
當你需要經常在服務器上校驗數據時,在Web頁面上的另加校驗就有諸多好處。多數情況下,用戶會被表單惹惱。而當用戶填完表單時就校驗數據,既有助于用戶立即發現他們犯的錯誤,也能減少等待HTTP響應的時間、并減少服務器對錯誤表單輸入的處理。本文介紹的,就是如何在表單所在頁面對表單數據進行校驗。
使用瀏覽器內置的表單校驗
HTML5的一大特性,就是在不依賴腳本的情況下校驗大多數的用戶數據。該特性是通過使用表單元素上的校驗特性來實現的。
元素校驗不通過時
當一個元素校驗不通過時,會發生兩件事:
該元素會匹配到:invalid這個CSS偽類,它能讓你給校驗不過的元素提供特定的樣式。類似地,校驗通過的元素則會匹配:valid偽類。
當用戶要發送數據時,瀏覽器會阻止這個表單、并展示一段錯誤信息。
元素的校驗約束
所有的元素都能使用pattern特性來作校驗。該特性采用一個區分大小寫的正則表達式作為它的值。若元素的值非空、或者不匹配該特性所指定的正則表達式,該元素就會被認為是校驗不通過的。
舉個例子
Would you prefer a banana or a cherry?
Submit
input:invalid {
border: 1px solid red;
}
input:valid {
border: 1px solid green;
}
在本例中,元素可以接受如下三種值:空字符串、字符串"banana"或"cherry"。
required特性
若某個元素需要在提交表單之前填一個值,那我們可以通過required特性來標記該元素。當該特性為true時,所在的文本域不允許為空。
Would you prefer a banana or cherry?
Submit
input:invalid {
border: 1px solid red;
}
input:valid {
border: 1px solid green;
}
注意文本框相比上個例子有何不同:
注意:元素的type特性被設為email或url時,無需再使用pattern特性來坐校驗。指定email類型時,文本框的值就得是個正確格式的email地址(同時指定mutiple特性時,還可以是一個逗號分隔的email地址列表)。指定url類型的文本框則會自動匹配一個URL。
其他校驗約束
所有接受用戶輸入的表單元素(, 等)都支持required特性,但要注意元素并不支持pattern特性。
所有的文本輸入框(或)都可以使用maxlength特性來約束文本大小。輸入框的值若大于maxlength指定的值,就會校驗不通過。但是瀏覽器通常不會讓用戶輸入超過文本框指定長度的文本。
對于數字輸入框,min和max特性也提供了校驗約束。若輸入框的值小于min的值或大于max的值,輸入框就會校驗不通過。
來個完整點的例子:
Title*
Mr.
Ms.
How old are you?
pattern="\d+">
What's your favorite fruit?*
pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range">
Banana
Cherry
Apple
Strawberry
Lemon
Orange
What's your e-mail?
Leave a short message
Submit
body {
font: 1em sans-serif;
padding: 0;
margin : 0;
}
form {
max-width: 200px;
margin: 0;
padding: 0 5px;
}
p > label {
display: block;
}
input[type=text],
input[type=email],
input[type=number],
textarea,
fieldset {
/* 需要給Webkit瀏覽器下的表單元素適當的樣式 */
-webkit-appearance: none;
width : 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
input:invalid {
box-shadow: 0 0 5px 1px red;
}
input:focus:invalid {
outline: none;
}
定制錯誤信息
如我們上面看到的幾個例子所示,每次用戶要發送未通過校驗的表單時,瀏覽器都會展示一段錯誤信息。該信息的展示方式取決于瀏覽器本身。
這些自動生成的信息有兩大缺點:
沒有標準的方法來用CSS改變其外觀和體驗。
它們還要依賴瀏覽器本地信息,這意味著你會在使用一種語言的頁面中,遇到錯誤信息使用另一種語言展示的情況。
使用法語版本的瀏覽器瀏覽英文頁面
瀏覽器
渲染效果
Firefox 17 (Windows 7)
Chrome 22 (Windows 7)
Opera 12.10 (Mac OSX)
要定制這些信息的外觀和文本,你必須使用JavaScript,沒有只使用HTML和CSS的方法。
HTML5提供了約束驗證API來檢查和定制表單元素的狀態。此外它也能改變錯誤信息的文本。來看個例子:
I would like you to provide me an e-mail
Submit
在Javascript中,你可以調用setCustomValidity())方法:
var email = document.getElementById("mail");
email.addEventListener("keyup", function (event) {
if (email.validity.typeMismatch) {
email.setCustomValidity("I expect an e-mail, darling!");
} else {
email.setCustomValidity("");
}
});
使用Javascript校驗表單
若你想要控制錯誤信息的樣式和效果,或者想處理那些不支持HTML5表單驗證的瀏覽器,那你就只能使用Javascript了。
HTML5約束驗證API
現在越來越多的瀏覽器開始支持約束驗證API,而且也支持得越來越靠譜。該API囊括了各個表單元素上的一系列方法和屬性。
約束驗證API的屬性
屬性
描述
validationMessage
可以是一段本地化的信息,用于描述表單控件所不滿足的驗證條件(如果有的話);當控件不支持任何約束驗證(willValidae的值為false)、或控件的值滿足了約束條件時,也可以是一個空字符串
validity
一個用于描述元素校驗階段的validityState對象
validity.customError
元素觸發了定制的錯誤時返回true,否則返回false
validity.patternMismatch
元素的值不匹配提供的模板時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid偽類
validity.rangeOverflow
元素的值大于提供的最大值時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid和:out-fo-range偽類
validity.rangeUnderflow
元素的值小于提供的最小值時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid和:out-fo-range偽類
validity.stepMismatch
元素的值不符合step特性提供的規則時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid和:out-fo-range偽類
validity.tooLong
元素的值的長度超過要求的最大長度時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid和:out-fo-range偽類
validity.typeMismatch
元素的值不是正確的語法時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid偽類
validity.valid
元素的值沒有校驗出的問題時返回true,否則返回false。當返回true時,該元素會匹配CSS的:valid,否則會匹配:invalid偽類
validity.valueMissing
元素是必填項但沒有值時返回true,否則返回false。當返回true時,該元素會匹配CSS的:invalid偽類
willValidate
元素在表單提交時會被校驗則返回true,否則返回false
約束驗證API的方法
方法
描述
checkValidity()
元素的值沒有校驗出的問題時返回true,否則返回false。當校驗不通過時,該方法還會在相應元素上觸發invalid事件。
setCustomValidity(message)
給元素添加一段定制的錯誤信息;若你手動設置了錯誤信息,則給元素會被當做校驗未通過,并顯示出特定的錯誤。這就能讓你擺脫標準的約束驗證API提供的錯誤信息,直接使用Javascript來建立自己的錯誤信息。該信息在報錯時會展示給用戶。
對于老舊瀏覽器,我們可以使用H5F之類的polyfill來彌補其對于約束驗證API的不支持。由于這里你已經使用了Javascript,所以使用polyfill也并不會成為你設計或實現網站、Web應用時的額外負擔。
使用約束驗證API的例子
來看下如何使用該API來建立定制的錯誤信息,首先HTLM如下:
Please enter an email address:
Submit
這個簡單的表格用了novalidate特性來關閉瀏覽器的自動校驗;這樣我們的腳本就能控制整個校驗過程了。但是這樣做卻不會禁用掉約束驗證API、以及 :valid, :invalid, :in-range, :out-of-range 等一系列CSS偽類。這就意味著,雖然瀏覽器不會自動在表單發送前校驗它的數據,但你仍可自己來做校驗、并且按需給予表單樣式。
aria-live特性用來確保我們定制的錯誤信息能展示給任何人,包括那些使用諸如屏幕閱讀器等無障礙設備的人。
CSS
這段CSS用于裝飾我們的表單、并讓錯誤的輸出看起來更吸引人些。
/* 這段只是用來美化表單 */
body {
font: 1em sans-serif;
padding: 0;
margin : 0;
}
form {
max-width: 200px;
}
p * {
display: block;
}
input[type=email]{
-webkit-appearance: none;
width: 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* 這段是給校驗未通過的輸入框的樣式 */
input:invalid{
border-color: #900;
background-color: #FDD;
}
input:focus:invalid {
outline: none;
}
/* 這段是給錯誤信息的樣式 */
.error {
width : 100%;
padding: 0;
font-size: 80%;
color: white;
background-color: #900;
border-radius: 0 0 5px 5px;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.error.active {
padding: 0.3em;
}
JavaScript
下面的Javascript代碼用來處理我們自定義的錯誤校驗。
// 獲取DOM節點的方法有許多,這里我們獲取了表單自身以及email輸入框,還有一個讓我們放置錯誤信息的span元素。
var form = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');
var error = document.querySelector('.error');
email.addEventListener("keyup", function (event) {
// 每次用戶輸入時,我們都會檢查email輸入框是否合法
if (email.validity.valid) {
// 當校驗通過時,如果已經有一段錯誤信息在顯示了,就移除掉錯誤信息
error.innerHTML = ""; // 重置消息內容
error.className = "error"; // 重置消息的顯示狀態
}
}, false);
form.addEventListener("submit", function (event) {
// 每次用戶要提交表單時,我們都會檢查email輸入框是否合法
if (!email.validity.valid) {
// 如果輸入框不合法,我們就展示那段定制的錯誤信息
error.innerHTML = "I expect an e-mail, darling!";
error.className = "error active";
// 通過取消事件來阻止表單提交
event.preventDefault();
}
}, false);
下面是運行結果:
約束驗證API給了我們處理表單校驗的強大工具,并讓我們能有力地控制其用戶界面,這就遠超過只用HTML和CSS所能做的事了。
不使用內置API來校驗表單
有時,面對老舊瀏覽器和[定制的組件](),你不能(或者不想)使用約束驗證API。但在這種情況下,你仍然可以使用Javascript來校驗你的表單。表單的校驗更多是個用戶界面的問題、而非真正的數據校驗。
要校驗一個表單,你得先問你自己幾個問題:
我需要進行什么類型的校驗?
你得先決定如何校驗數據,這取決于你:可以用字符串操作、類型轉換、正則表達式等等。只要記住表單數據通常是一段文本,而且傳到你的腳本里時也是一些字符串就好。
表單校驗未通過時,我應該做什么?
這就是個UI的問題了。得靠你決定表單的行為:是不論是否通過都發送數據呢?還是高亮那些出現錯誤的字段?還是展示一些錯誤信息?
如何幫助用戶用戶糾正非法數據?
要減少用戶的不滿,很重要的是提供盡可能多的幫助信息,以指導用戶糾正他們的輸入。還應該提供些前置的輸入建議、和清晰的錯誤信息,讓用戶知道該輸入什么。
若你還想深入了解表單校驗的UI要求,可以讀讀下面這些有用的文章:
未使用約束驗證API的例子
為了更好地說明,我們接下來要重構上述的例子,讓它能在老舊瀏覽器上運行:
Please enter an email address:
Submit
如你所見,HTML的和之前幾乎一模一樣;這里只移除了HTML5的部分。要注意的是ARIA是個并不依賴于HTML5的獨立特性,所以我們仍會保留它。
CSS
類似地,CSS不需要做大規模修改;只要把:invalid偽類轉為真的類,并且不去使用IE6不支持的特性選擇器即可。
/* 這段只是用來美化表單 */
body {
font: 1em sans-serif;
padding: 0;
margin : 0;
}
form {
max-width: 200px;
}
p * {
display: block;
}
input.mail {
-webkit-appearance: none;
width: 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* 這段是給校驗未通過的輸入框的樣式 */
input.invalid{
border-color: #900;
background-color: #FDD;
}
input:focus.invalid {
outline: none;
}
/* 這段是給錯誤信息的樣式 */
.error {
width : 100%;
padding: 0;
font-size: 80%;
color: white;
background-color: #900;
border-radius: 0 0 5px 5px;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.error.active {
padding: 0.3em;
}
JavaScript
Javascript代碼的改變最大,為了兼容我們需要做更多的事情。
// 老舊瀏覽器上獲取DOM節點的方法少了些
var form = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');
// 下面是個訪問DOM里下個兄弟元素節點的的技巧
// 但這樣做很危險,因為很容易就會建立一個死循環
// 在現代瀏覽器上,應該使用element.nextElementSibling
var error = email;
while ((error = error.nextSibling).nodeType != 1);
// 按照HTML5的規范來
var emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
// 許多老舊瀏覽器不支持addEventListener方法
// 下面是個解決該問題的簡單方法,當然方法遠不止這一種
function addEvent(element, event, callback) {
var previousEventCallBack = element["on"+event];
element["on"+event] = function (e) {
var output = callback(e);
// 回調返回`false`時會終止回調鏈并結束事件回調的執行
if (output === false) return false;
if (typeof previousEventCallBack === 'function') {
output = previousEventCallBack(e);
if(output === false) return false;
}
}
};
// 現在可以來重構我們的校驗了
// 由于我們不依賴CSS偽類,故而必須在email字段明確設置valid/invalid類
addEvent(window, "load", function () {
// 這里我們檢驗該字段是否為空(注意,該字段不是必填的)
// 若不是,我們再檢驗它的內容是否為正確格式的email地址
var test = email.value.length === 0 || emailRegExp.test(email.value);
email.className = test ? "valid" : "invalid";
});
// 定義用戶在該字段輸入時會發生什么
addEvent(email, "keyup", function () {
var test = email.value.length === 0 || emailRegExp.test(email.value);
if (test) {
email.className = "valid";
error.innerHTML = "";
error.className = "error";
} else {
email.className = "invalid";
}
});
// 定義用戶提交數據時會發生什么
addEvent(form, "submit", function () {
var test = email.value.length === 0 || emailRegExp.test(email.value);
if (!test) {
email.className = "invalid";
error.innerHTML = "I expect an e-mail, darling!";
error.className = "error active";
// 某些老舊瀏覽器不支持event.preventDefault()方法
return false;
} else {
email.className = "valid";
error.innerHTML = "";
error.className = "error";
}
});
結果如下所示:
如你所見,自己建立一個校驗系統并不是一件難事。難點就在于如何跨平臺、并在你創建的任何表單上都能使用它?,F在有許多庫能執行表單校驗,你應該毫不猶豫地使用他們。如下是幾個例子:
遠端校驗
有些情況下使用遠端校驗還是挺有用的。在用戶輸入的數據得添加到應用服務器的數據存儲時,這種校驗是有必要的。一個相應的例子就是需要填用戶名的注冊表單。為避免用戶名重復,更聰明的辦法是發送一個AJAX請求來檢查用戶名的可用性,而不是讓用戶發送完數據、然后再返回一個帶有錯誤的表單。
使用這種校驗,需要注意以下幾點:
因為需要公開暴露API和一些數據,所以得保證數據不是敏感的。
由于網絡存在延遲,故得進行異步校驗。這就得靠一些UI設計來保證校驗不能正確執行時,用戶操作不至于被阻塞。
結論
表單校驗并不用靠復雜的Javascript,但它要求我們認真為用戶著想,始終得幫用戶糾正他們輸入的數據。要做到這點,請確保:
展示明確的錯誤信息
約定好輸入格式
指出錯誤出現的確切位置(特別是在那些巨大的表單中)
總結
以上是生活随笔為你收集整理的html5 数据验证,【译】表单数据校验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html网页大小自动调整大小,根据电脑屏
- 下一篇: 心电图QTC延长是什么意思