本文探討HTML表單欄位及HTML5提供的驗證選項,並討論如何透過CSS和JavaScript增強這些功能。
何謂約束驗證?
每個表單欄位都有其目的,而這目的常受約束(即規範每個表單欄位應輸入與不應輸入內容的規則)所支配。例如,email
欄位需輸入有效電郵地址;password
欄位可能要求特定字符類型及最小字符數;而文字欄位可能限制可輸入的字符數量。
現代瀏覽器能檢查用戶是否遵守這些約束,並在規則被違反時發出警告。這稱為約束驗證。
客戶端與伺服器端驗證
JavaScript早期大量程式碼處理客戶端表單驗證。即便今日,開發者仍花費大量時間編寫檢查欄位值的函數。在現代瀏覽器中,這是否仍必要?可能不必要。大多情況下,這取決於你的需求。
但首先,一個重要警告:
客戶端驗證是項便利功能,能在應用程式浪費時間和頻寬將數據傳送至伺服器前,防止常見數據輸入錯誤。但它不能取代伺服器端驗證!
始終在伺服器端清理數據。並非每個請求都會來自瀏覽器。即使確實來自瀏覽器,也無法保證瀏覽器已驗證數據。任何知道如何打開瀏覽器開發工具的人也可以繞過您精心製作的HTML和JavaScript。
HTML5輸入欄位
HTML提供:
<textarea>
用於多行文字框<select>
用於下拉選項列表<button>
用於…按鈕
但您最常用的是<input>
:
<input type="text" name="username" />
type
屬性設置控制類型,並有多種選擇:
type |
description |
---|---|
button |
a button with no default behavior |
checkbox |
a check/tick box |
color |
a color picker |
date |
a date picker for the year, month, and day |
datetime-local |
a date and time picker |
email |
an email entry field |
file |
a file picker |
hidden |
a hidden field |
image |
a button which displays the image defined by the src attribute |
month |
a month and year picker |
number |
a number entry field |
password |
a password entry field with obscured text |
radio |
a radio button |
range |
a slider control |
reset |
a button that resets all form inputs to their default values (but avoid using this, as it’s rarely useful) |
search |
a search entry field |
submit |
a form submission button |
tel |
a telephone number entry field |
text |
a text entry field |
time |
a time picker with no time zone |
url |
a URL entry field |
week |
a week number and year picker |
如果省略type
屬性或瀏覽器不支持某個選項,瀏覽器將默認為text
。現代瀏覽器對所有類型都有良好的支持,但舊瀏覽器仍將顯示文字輸入欄位。
其他有用的<input>
屬性包括:
attribute | description |
---|---|
accept |
file upload type |
alt |
alternative text for the image types |
autocomplete |
hint for field auto-completion |
autofocus |
focus field on page load |
capture |
media capture input method |
checked |
checkbox/radio is checked |
disabled |
disable the control (it won’t be validated or have its value submitted) |
form |
associate with a form using this ID |
formaction |
URL for submission on submit and image buttons |
inputmode |
data type hint |
list |
ID of <datalist> autocomplete options |
max |
maximum value |
maxlength |
maximum string length |
min |
minimum value |
minlength |
minimum string length |
name |
name of control, as submitted to server |
pattern |
a regular expression pattern, such as [A-Z]+ for one or more uppercase characters |
placeholder |
placeholder text when the field value is empty |
readonly |
the field is not editable, but it will still be validated and submitted |
required |
the field is required |
size |
the size of the control (often overridden in CSS) |
spellcheck |
set true or false spell-checking |
src |
image URL |
step |
incremental values in numbers and ranges |
type |
field type (see above) |
value |
the initial value |
HTML輸出欄位
除了輸入類型,HTML5還提供只讀輸出:
輸出
:計算或用戶操作的文字結果進度
:具有value
和max
屬性的進度條儀表
:一個刻度,可以根據value
、min
、max
、low
、high
和optimum
屬性的設定值在綠色、琥珀色和紅色之間變化。
輸入標籤
欄位應該有一個相關聯的<label>
,你可以將元素包裹在其中:
<label>your name <input type="text" name="name" /><label>
或者使用for
屬性將欄位的id
與標籤連接:
<label for="nameid">your name</label>
<input type="text" id="nameid" name="name" />
標籤對於可訪問性很重要。你可能遇到過使用placeholder
來節省屏幕空間的表單:
<input type="text" name="name" value="" placeholder="your name" />
占位符文本在用戶輸入任何內容(甚至是單個空格)後消失。顯示標籤比強迫用戶記住欄位所需的信息更好!
輸入行為
欄位類型和約束屬性改變瀏覽器的輸入行為。例如,number
輸入在移動設備上顯示數字鍵盤。該欄位可能顯示一個微調器,並且鍵盤上下游標按鍵將增加和減少值。
大多數欄位類型顯而易見,但也有例外。例如,信用卡號碼雖然是數字,但使用增減微調器並無意義,且在輸入16位數字時很容易誤按上下鍵。較佳做法是使用標準的text
類型,但將inputmode
屬性設為numeric
,以顯示合適的鍵盤。同時設定autocomplete="cc-number"
也能提示任何已配置或先前輸入的信用卡號碼。
使用正確的欄位type
和autocorrect
能帶來難以透過JavaScript實現的優勢。例如,某些移動瀏覽器能夠:
- – 通過相機掃描信用卡來導入信用卡詳細信息
- – 導入由SMS發送的一次性代碼
自動驗證
瀏覽器會確保輸入值符合type
、min
、max
、step
、minlength
、maxlength
、pattern
及required
屬性定義的約束。例如:
<input type="number" min="1" max="100" required />
嘗試提交空值會阻止表單提交,並在Chrome中顯示以下訊息:
旋轉器將不允許超出1至100範圍的數值。若您輸入的字串並非數字,也會出現類似的驗證提示訊息。所有這些都不需要一行JavaScript代碼。
您可以通過以下方式阻止瀏覽器驗證:
- 在
<form>
元素上添加novalidate
屬性 - 在提交按鈕或圖像上添加
formnovalidate
屬性
創建自定義JavaScript輸入
如果您正在編寫一個新的JavaScript日期輸入組件,請立即停止並遠離您的鍵盤!
編寫自定義輸入控制相當困難。您必須考慮到鼠標、鍵盤、觸摸、語音、可訪問性、屏幕尺寸,以及當JavaScript失效時會發生什麼。您也在創建一個不同的用戶體驗。也許您的控制在桌面、iOS和Android上比標準日期選擇器更優越,但這個不熟悉的用戶界面會讓一些用戶感到困惑。
開發者選擇創建JavaScript輸入主要有三個原因。
1. 標準控制難以樣式化
CSS樣式化有限,通常需要使用如覆蓋輸入及其標籤的::before
和::after
偽元素等技巧。情況正在改善,但質疑任何優先考慮形式而非功能的設計。
2. 舊版瀏覽器不支持現代<input>
類型
本質上,你是在為Internet Explorer編碼。IE用戶不會獲得日期選擇器,但仍可以YYYY-MM-DD
格式輸入日期。如果客戶堅持,那麼僅在IE中加載polyfill即可。沒有必要讓現代瀏覽器承擔這個負擔。
3. 你需要一種從未實現過的新輸入類型
這些情況很少見,但總是從適當的HTML5字段開始。它們快速,甚至在腳本加載之前就能工作。你可以根據需要逐步增強字段。例如,一點JavaScript可以確保日曆事件的結束日期在開始日期之後。
總結:避免重新發明HTML控制項!
CSS驗證樣式
你可以將以下偽類應用於輸入字段,根據當前狀態對其進行樣式設置:
selector | description |
---|---|
:focus |
the field with focus |
:focus-within |
an element contains a field with focus (yes, it’s a parent selector!) |
:focus-visible |
an element has focus owing to keyboard navigation, so a focus ring or more evident styling is necessary |
:required |
a field with a required attribute |
:optional |
a field without a required attribute |
:valid |
a field that has passed validation |
:invalid |
a field that has not passed validation |
:user-valid |
a field that has passed validation after the user has interacted with it (Firefox only) |
:user-invalid |
a field that hasn’t passed validation after the user has interacted with it (Firefox only) |
:in-range |
the value is within range on a number or range input |
:out-of-range |
the value is out of range on a number or range input |
:disabled |
a field with a disabled attribute |
:enabled |
a field without a disabled attribute |
:read-only |
a field with a read-only attribute |
:read-write: |
a field without a read-only attribute |
:checked |
a checked checkbox or radio button |
:indeterminate |
an indeterminate checkbox or radio state, such as when all radio buttons are unchecked |
:default |
the default submit button or image |
你可以使用::placeholder
偽元素對輸入的placeholder
文本進行樣式設置:
/* 電子郵件字段上的藍色佔位符 */
input[type="email"]::placeholder {
color: blue;
}
上述選擇器的特異性相同,因此順序可能很重要。考慮以下示例:
input:invalid { color: red; }
input:enabled { color: black; }
無效輸入具有紅色文本,但它僅應用於具有disabled
屬性的輸入——因此所有啟用的輸入都是黑色的。
瀏覽器在頁面加載時應用驗證樣式。例如,在以下代碼中,每個無效字段都會被賦予紅色邊框:
:invalid {
border-color: #900;
}
用戶在與表單互動之前面對的是一組令人畏懼的紅色警示框。若在首次提交後或值更改時顯示驗證錯誤,將提供更佳的使用體驗。這正是JavaScript發揮作用的時刻……
JavaScript與約束驗證API
約束驗證API(Constraint Validation API)提供了增強標準HTML字段檢查的表單自定義選項。您可以:
- 阻止驗證直至用戶與字段互動或提交表單
- 以自定義樣式顯示錯誤信息
- 提供僅憑HTML無法實現的自定義驗證。當您需要比較兩個輸入時,這通常是必要的——例如,當您輸入電子郵件地址或電話號碼時,檢查“新”和“確認”密碼字段是否具有相同值,或者確保一個日期在另一個日期之後。
表單驗證
在使用API之前,您的代碼應通過將表單的noValidate
屬性設置為true
(相當於添加novalidate
屬性)來禁用默認驗證和錯誤信息:
const myform = document.getElementById('myform');
myform.noValidate = true;
接著,您可以添加事件處理程序——例如,當表單提交時:
myform.addEventListener('submit', validateForm);
處理程序可以使用checkValidity()
或reportValidity()
方法檢查整個表單是否有效,這些方法在所有表單輸入均有效時返回true
。(差異在於checkValidity()
檢查是否有任何輸入受到約束驗證的影響。)
根據 Mozilla 文件 解釋:
每個無效欄位也會觸發
invalid
事件。此事件不會冒泡:處理程序必須添加到每個使用它的控制項上。
// 提交時驗證表單
function validateForm(e) {
const form = e.target;
if (form.checkValidity()) {
// 表單有效 - 進行進一步檢查
}
else {
// 表單無效 - 取消提交
e.preventDefault();
}
};
A valid form could now incur further validation checks. Similarly, an invalid form could have invalid fields highlighted.
欄位驗證
個別欄位具有以下約束驗證屬性:
-
willValidate
: 如果元素是約束驗證的候選者,則返回true
。 -
validationMessage
: 驗證消息。如果欄位有效,則此消息將為空字符串。 -
valitity
: 一個 ValidityState 物件。當欄位有效時,此物件的valid
屬性會被設為true
。若為false
,則下列一或多個屬性將會是true
:ValidityState 描述 .badInput
瀏覽器無法理解輸入 .customError
已設定自訂有效性訊息 .patternMismatch
值不符合指定的 pattern
屬性.rangeOverflow
值大於 max
屬性.rangeUnderflow
值小於 min
屬性.stepMismatch
值不符合 step
屬性的規則.tooLong
字串長度大於 maxlength
屬性.tooShort
字串長度小於 minlength
屬性.typeMismatch
值不是有效的電子郵件或 URL .valueMissing
一個 required
值為空
個別欄位具有以下約束驗證方法:
setCustomValidity(message)
: 為無效欄位設定錯誤訊息。當欄位有效時,必須傳遞空字串,否則欄位將永久保持無效狀態。checkValidity()
: 當輸入有效時返回true
。valitity.valid
屬性具有相同功能,但checkValidity()
還會在欄位上觸發一個invalid
事件,這可能會很有用。
處理函數 validateForm()
可以遍歷每個欄位,並在必要時將 invalid
類別應用到其父元素:
function validateForm(e) {
const form = e.target;
if (form.checkValidity()) {
// 表單有效 - 進行進一步檢查
}
else {
// 表單無效 - 取消提交
e.preventDefault();
// 應用無效類別
Array.from(form.elements).forEach(i => {
if (i.checkValidity()) {
// 欄位有效 - 移除類別
i.parentElement.classList.remove('invalid');
}
else {
// 欄位無效 - 添加類別
i.parentElement.classList.add('invalid');
}
});
}
};
假設您的 HTML 定義了一個電子郵件欄位:
<div>
<label for="email">email</label>
<input type="email" id="email" name="email" required />
<p class="help">Please enter a valid email address</p>
</div>
當電子郵件未指定或無效時,腳本會將 invalid
類別應用於 <div>
。當表單提交時,CSS 可以顯示或隱藏驗證訊息:
.help { display: none; }
.invalid .help { display: block; }
.invalid label, .invalid input, .invalid .help {
color: red;
border-color: red;
}
建立自訂表單驗證器
以下示範展示了一個需要使用者名稱以及電子郵件地址、電話號碼或兩者之一的聯絡表單範例:
此功能透過名為 FormValidate
的通用表單驗證類別實現。在實例化對象時傳遞表單元素。可以設置一個可選的第二個參數:
true
以在使用者與其互動時驗證每個欄位false
(預設值)以在首次提交後驗證所有欄位(欄位級別驗證在此之後發生)
// 驗證聯絡表單
const contactForm = new FormValidate(document.getElementById('contact'), false);
.addCustom(field, func)
方法定義自訂驗證函數。以下程式碼確保 email
或 tel
欄位有效(兩者均無 required
屬性):
// 自訂驗證 - 電子郵件和/或電話
const
email = document.getElementById('email'),
tel = document.getElementById('tel');
contactForm.addCustom(email, f => f.value || tel.value);
contactForm.addCustom(tel, f => f.value || email.value);
A FormValidate
object monitors both of the following:
focusout
事件,隨後檢查個別欄位- 表單
submit
事件,隨後檢查每個欄位
兩者都調用 .validateField(field)
方法,該方法檢查欄位是否通過標準約束驗證。當它通過時,分配給該欄位的任何自訂驗證函數將依次執行。所有函數都必須返回 true
以使該欄位有效。
無效欄位會在其父元素上應用invalid
類別,透過CSS顯示紅色協助訊息。
最後,當整個表單有效時,該物件會呼叫自訂的submit
函數:
// 自訂提交
contactForm.submit = e => {
e.preventDefault();
alert('Form is valid!\n(open the console)');
const fd = new FormData(e.target);
for (const [name, value] of fd.entries()) {
console.log(name + ': ' + value);
}
}
或者,您可以使用標準的addEventListener
來處理表單submit
事件,因為FormValidate
在表單無效時會阻止其他處理程序運行。
表單精煉
表單是所有網路應用程式的基礎,開發者花費大量時間操作使用者輸入。約束驗證得到良好支援:瀏覽器能處理大多數檢查並顯示適當的輸入選項。
建議:
- 盡可能使用標準HTML輸入類型。根據需要設定
min
、max
、step
、minlength
、maxlength
、pattern
、required
、inputmode
和autocomplete
屬性。 - 如有必要,使用少量JavaScript來啟用自訂驗證和訊息。
- 對於更複雜的欄位,逐步增強標準輸入。
最後:忘掉Internet Explorer吧!
除非您的客戶主要使用IE瀏覽器,否則無需實現自己的回退驗證功能。所有HTML5輸入欄位在IE中均可使用,但可能需要用戶付出更多努力。(例如,IE不會檢測您輸入的電子郵件地址是否無效。)您仍然需要在伺服器端驗證數據,因此請考慮將其作為IE錯誤檢查的基礎。
HTML表單與約束驗證常見問題解答
HTML表單驗證的重要性是什麼?
HTML表單驗證是Web開發的一個重要方面。它確保用戶在表單中輸入的數據在發送到伺服器之前符合某些標準。這不僅保持了數據的完整性,還通過提供有關輸入數據正確性的即時反饋來增強用戶體驗。如果沒有表單驗證,則存在接收錯誤、不完整甚至惡意數據的風險,這可能導致數據損壞、安全漏洞和系統崩潰等各種問題。
HTML5如何改進表單驗證?
HTML5引入了多種新的表單元素和屬性,使表單驗證更加容易和高效。例如,它提供了新的輸入類型,如電子郵件、URL和數字,這些類型根據類型自動驗證輸入數據。它還引入了新屬性,如required、pattern和min/max,允許您對輸入數據指定各種約束。此外,HTML5提供了一個內置的驗證API,使您能夠使用JavaScript執行自定義驗證。
我可以在不使用JavaScript的情況下進行表單驗證嗎?
是的,您可以仅使用HTML5执行基本的表单验证。HTML5引入了多种新的输入类型和属性,允许您对输入数据指定各种约束。例如,您可以使用required属性使字段成为必填项,使用pattern属性强制特定格式,以及使用min/max属性为数值输入设置范围。然而,对于更复杂的验证,您可能仍然需要使用JavaScript。
如何在HTML5中自定义错误消息?
HTML5提供了一个验证API,允许您自定义错误消息。您可以使用ValidityState对象的setCustomValidity方法为字段设置自定义错误消息。此方法接受一个字符串参数,当字段无效时,该参数将成为字段的验证消息。您可以在字段验证失败时触发的invalid事件响应中调用此方法。
如何禁用HTML5表单验证?
您可以通过在form元素上添加novalidate属性来禁用HTML5表单验证。当此属性存在时,浏览器在提交表单时不会执行任何验证。如果您想完全在服务器端处理验证或使用自定义JavaScript进行验证,这会很有用。
如何在HTML5中一起验证多个字段?
HTML5 並未內建驗證多個欄位的方法。不過,您可以使用 JavaScript 達成此目的。您可以撰寫一個自訂驗證函數,檢查多個欄位的值,若它們不符合所需條件,則設定一個自訂的有效性訊息。您可以在表單的提交事件或欄位的輸入/變更事件中呼叫此函數。
如何在 HTML5 中根據另一個欄位的值驗證一個欄位?
HTML5 不提供內建方法來根據另一個欄位的值驗證欄位。但您可以使用 JavaScript 達成此目的。您可以撰寫一個自訂驗證函數,檢查一個欄位的值是否與另一個欄位的值相符,若不匹配,則設定一個自訂的有效性訊息。您可以在欄位的輸入/變更事件中呼叫此函數。
如何在 HTML5 中進行非同步驗證?
HTML5 本身不支援非同步驗證。但您可以使用 JavaScript 達成此目的。您可以撰寫一個自訂驗證函數,執行非同步操作,如 AJAX 請求,並根據結果設定一個自訂的有效性訊息。您可以在欄位的輸入/變更事件或表單的提交事件中呼叫此函數。
如何在 HTML5 表單驗證中設計錯誤訊息的樣式?
在HTML5表单验证中,错误信息的外观由浏览器决定,无法直接通过CSS进行样式设置。不过,您可以利用JavaScript创建自定义错误信息,并随心所欲地设计它们的样式。通过使用验证API,您可以在字段无效时确定这一情况,并相应地显示自定义错误信息。
如何测试HTML表单的验证功能?
您可以通过在表单字段中输入各种类型的数据并尝试提交表单来测试HTML表单的验证。您应当使用有效和无效数据进行测试,确保验证在所有情况下都能正确工作。此外,您还可以利用自动化测试工具或库进行更为全面的测试。
Source:
https://www.sitepoint.com/html-forms-constraint-validation-complete-guide/