HTML5 為我們帶來了很多非常好的優勢。除了統一錯誤模型、引入新語義標籤或簡化文件類型等常見問題之外,最大的改進之一是表單的限制驗證。如果沒有表單,網路會是什麼樣子?
約束驗證試圖提高 Web 表單的可用性。瀏覽器可以直接告知使用者無效值的可能性,而不是將表單傳送到伺服器,然後將其評估為無效,返回客戶端並最終由使用者進行調整。這不僅減少了網路通信,還提高了頁面的可用性。
要注意的是,約束驗證不能取代伺服器端驗證。此外,基於 JavaScript 的解決方案可能仍然有用。一般來說,我們總是必須實作伺服器端驗證。如果我們使用良好的架構,伺服器上的模型約束將自動反映在傳輸的 HTML 程式碼中。這樣我們就可以免費獲得約束驗證。現在我們可以使用 JavaScript 進一步增強體驗,它既可以充當約束驗證的補充,也可以充當填充。
我們將從非驗證表單開始我們的旅程。然後我們將整合一個基於 JavaScript 的解決方案。最後介紹一下HTML5的約束驗證。在最後一節中,我們將了解可能遇到的跨瀏覽器奇怪現象。
最經典的 HTML 表單版本是不帶有任何用戶端驗證邏輯的版本。我們只需要提供一個標準的形式,不需要任何特殊的屬性。正如簡介中已經指出的,我們需要始終特別注意這種表單提交。
儘管我們確實希望保護客戶端上已經存在的表單,但我們永遠無法確定所提交資料的狀態。保護和增強伺服器上的表單驗證的技術很大程度上取決於所使用的程式框架和語言。因此我們將跳過這樣的討論。相反,我們現在將討論一般的表單提交。
在《精通HTML5》系列的第二部分中我們已經提到了表單編碼類型的重要性。我們也研究了三種成熟的編碼類型。剩下的問題是:這些價值觀實際上是如何建立的?瀏覽器的確切行為取決於為 action
指定的協定。為了簡單起見,我們現在假設 HTTP 或 HTTPS。
原則上,瀏覽器有兩個選項:
兩者的程式大致相同。簡而言之,我們發現以下步驟:
表單資料集的建構意味著一些微妙的問題,但這些問題並不是很為人所知。例如,如果按一下按鈕來提交表單,情況就會有所不同。在這種情況下,按鈕的值將傳輸到伺服器。這可用於確定按下了哪個按鈕。
如果我們按下第一個按鈕,那麼以下內容將會被傳送到伺服器。
foo=bar
從 JavaScript 觸發表單提交將導致不傳輸任何內容。 JavaScript 程式碼使用 HTMLFormElement
實例的 submit()
方法。
另一個有趣的方面是使用 image
類型提交輸入元素的點擊座標。 image
輸入類型不久前非常流行,人們認為檢查使用者點擊的位置是個好主意。也許所顯示的圖像表明了幾種可能性。然後伺服器將負責評估用戶的請求。
以下範例說明了此行為。
如果我們點擊圖片提交表單,就會考慮foo
的資料。僅當值存在時才會插入名稱-值對。此外,我們需要命名輸入元素,否則不會傳輸任何內容。
請求的內容可能類似於以下程式碼片段。
foo.x=71&foo.y=38&foo=bar
此外,我們應該注意不考慮禁用欄位。這是有道理的。因此,下面的表格考慮了具有兩個輸入欄位(一個啟用和一個停用)的前兩個範例,可以建構為概念證明。
#以程式設計方式提交表單將導致傳輸單一值。
即使沒有約束驗證或 JavaScript,瀏覽器也已經為我們提供了一些簡單的表單驗證。正如我們之前所看到的,表單的狀態(例如啟用或停用)和提交者都會被考慮。但是,這些都不會阻止表單的提交。一個簡單的方法是寫一些 JavaScript 來處理可能中止進程的情況。
JavaScript 的最初用途之一实际上是为表单提供增强的功能。基本思想是在即将提交表单时收到事件通知。此时我们可以检查所有值并中止该过程。当然,我们可以改进整个想法,以便在任何值发生变化时始终进行检查。尽管如此,最终我们可能会根据我们最后的评估而中止提交。
var form = document.querySelector('form'); form.addEventListener('submit', function (ev) { // always abort! ev.preventDefault(); }, false);
理论上进行实时验证很容易。然而,指定的 DOM 事件的工作方式可能与直观猜测的不同。例如,文本框的 change
事件仅在文本框失去焦点后才会触发。当用户单击提交按钮时可能会发生这种情况。因此,与验证的交互被破坏并且感觉不活跃。
相反,使用 keyup
或 input
事件是有意义的。虽然前者是文本框的有效解决方案,但后者适用于所有输入元素(如预期)。唯一的限制是它是随 HTML5 引入的,某些较旧的浏览器可能不支持。
考虑到这一点,让我们比较各个事件以查看执行顺序。下面的测试代码可以帮助我们。
var input = document.querySelector('input'); ['input', 'keyup', 'change'].forEach(function (eventName) { input.addEventListener(eventName, function (e) { console.log(eventName + ' event triggered'); }, false); });
对于我们的测试 <input>
元素,当使用几个字母进行探测时,我们会看到以下结果。最后我们使用 Tab 键显式地移开焦点。
正如我们所看到的,顺序设置为首先触发 input
事件,然后触发 keyup
。其实这是有道理的。首先我们需要 keydown
,然后该值可能会发生变化,从而导致 input
事件。最后我们释放密钥,这会产生一个 keyup
事件。值得强调的是,input
仅在值发生变化时才会触发,而 keyup
与实际值变化无关。举个例子,如果我们按箭头键,我们只会看到 keyup
事件,而看不到 input
事件。
可以通过向所有表单字段添加事件侦听器来对所有元素进行实时验证。或者,我们只需要为表单添加一个用于 input
事件的事件侦听器。尽管非常优雅,但这种方法有一个明显的缺点。
考虑以下非常简单的 HTML:
我们使用 HTML5 form
属性在其外部声明 <form></form>
的一个字段。但是,input
事件正常工作,因为这些事件实际上会在 DOM 树中冒泡。因此,外部场触发的特定事件将不会被看到。
因此,最可靠的方法是获取表单并迭代 elements
集合中给出的子项。这里收集所有分配的字段(image
输入类型除外)。
约束验证意味着我们能够在 HTML 源代码中指定约束,然后浏览器使用这些约束来检查表单。有很多可能性。很多选项与输入类型相关,不能随意使用。在我们深入研究不同的验证和实现怪癖之前,让我们先简要了解一下整体设计。
所选择的 API 旨在使我们能够进行快速检查。我们可以探测当前实例是否能够通过单个 API 调用进行约束验证。
API也非常开放,我们可以查询浏览器得到的结果,或者扩展浏览器的结果。伪接口Validation
也被其他接口继承,不仅仅是HTMLInputElement
。
让我们看一些示例代码。在下面的代码中,我们首先检查表单验证是否可行。如果是这样,那么我们关心 type=date
字段的验证结果。如果用户选择了有效日期,我们会检查复选框的状态。
var form = document.querySelector('form'); var date = document.querySelector('#birthday'); if (form.willValidate) { if (!date.validity.valid || checkbox.checked) checkbox.setCustomValidity(''); else checkbox.setCustomValidity('You need to agree to our terms.'); }
这样的条件逻辑(仅在某些情况下有效)不能单独使用标记来实现。但我们可以很好地将自定义逻辑与集成功能结合起来。
HTML5 知道很多不同的输入类型。但毕竟它们可以分为三类:
从 value
属性中看不到差异。这里我们总是得到 string
值。毕竟,该值将以文本形式提交。拥有这三个组的结果是针对某些类型的约束的不同行为。
以下限制幾乎總是以相同的方式運作:
required
,如果 value
的長度為零,則導致 valueMissing
minlength
,如果字串長度太短,會導致tooShort
maxlength
,如果字串長度太長,會導致tooLong
當然,也有例外。例如,複選框會對 required
作出反應,要求進行 checked
。如果顏色選擇是 required
且包含無效顏色,則顏色選擇將驗證為 valueMissing
。其他類型的反應類似。
其他可能的約束取決於輸入的特定類型。類型決定如何處理該值。是否將其視為文本?它代表一個數字嗎?約束對其做出反應。
我們以date
輸入類型為例。如果設定了有效日期,如果限制為 required
,我們會得到一個 valueMissing
。此外,如果實際輸入了某些內容,則會設定 badInput
。但是,如果日期有效,我們可能會出現以下一個或多個驗證錯誤:
rangeUnderflow
,如果日期低於 min
屬性中指定的日期rangeOverflow
,如果日期高於 max
屬性中指定的日期stepMismatch
,如果日期不滿足提供的step
模式最後一點相當有趣。這裡我們必須處理一種機制,該機制減去基數(可以是預設基數,也可以是 min 屬性中提供的)併計算可以對步驟取模的數字。對於日期輸入類型,計算並不完全明顯。實際提供的日期類型是不同的。然而,從使用者的角度來看,結果是有意義的。
對於文字輸入,還有 pattern
屬性,它允許我們指定用於驗證的正規表示式。如果輸入類型支援此約束,則會在失敗時記錄 patternMismatch
。
約束驗證使我們能夠為使用者(即使停用了 JavaScript)提供有關當前表單狀態的即時回饋。我們不必為了顯示錯誤訊息而浪費往返伺服器的網路頻寬。儘管如此,我們應該始終記住,表單提交通常是可以的。因此,在伺服器端進行一些驗證是不可避免的。
約束驗證所帶來的可能性幾乎是無限的。我們可以使用客戶端驗證來確保滿足正規表示式,考慮日期和數字的有效範圍,並選取某些複選框。我們也可以使用 JavaScript 擴充功能可用的檢查。
以上是掌握HTML5:約束驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!