本筆記記于2021年,摘自MDN HTML板塊
1.HTML表單是什么
HTML表單是用戶和web站點(diǎn)或應(yīng)用程序之間交互的主要內(nèi)容之一
允許用戶將數(shù)據(jù)發(fā)送到web站點(diǎn)
大多數(shù)情況下,數(shù)據(jù)被發(fā)送到web服務(wù)器,但是web頁(yè)面也可以自己攔截并使用
2.用HTML實(shí)現(xiàn)表單
form是一個(gè)容器元素,但它也支持一些特定的屬性來(lái)配置表單的行為方式
所有屬性都是可選的,最好至少要設(shè)置action屬性和method屬性
- action 屬性定義了在提交表單時(shí),應(yīng)該把所收集的數(shù)據(jù)送給誰(shuí)(/那個(gè)模塊)(URL)去處理
- method 屬性定義了發(fā)送數(shù)據(jù)的HTTP方法(它可以是“get”或“post”)
<label>元素上使用for屬性;它是將標(biāo)簽鏈接到表單小部件的一種正規(guī)方式,引用對(duì)應(yīng)的小部件的id,允許用戶單擊標(biāo)簽以激活相應(yīng)的小部件
在<input>元素中
type 屬性,定義了<input>屬性的行為方式,可從根本上改變?cè)?/p>
-
text,type屬性的默認(rèn)值
表示一個(gè)基本的單行文本字段,接受任何類(lèi)型的文本輸入 -
email,它定義了一個(gè)只接受格式正確的電子郵件地址的單行文本字段
要定義<input>的默認(rèn)值,必須使用value屬性
想定義<textarea>的默認(rèn)值,只需在<textarea>元素的開(kāi)始和結(jié)束標(biāo)記之間放置默認(rèn)值
<button>元素也接受一個(gè) type屬性,接受submit, reset或者 button 三個(gè)值中的任一個(gè)
-
submit:(也是默認(rèn)值)會(huì)發(fā)送表單的數(shù)據(jù)到<form>元素的action屬性所定義的網(wǎng)頁(yè) -
reset:將所有表單小部件重新設(shè)置為它們的默認(rèn)值 -
button:用JavaScript構(gòu)建定制按鈕
向web服務(wù)器發(fā)送表單數(shù)據(jù):
<form>元素將定義如何通過(guò)action屬性和method屬性來(lái)發(fā)送數(shù)據(jù)的位置和方式
要將數(shù)據(jù)命名為表單,需要在每個(gè)表單小部件上使用 name 屬性來(lái)收集特定的數(shù)據(jù)塊
3.構(gòu)造HTML表單
嚴(yán)格禁止在一個(gè)表單內(nèi)嵌套另一個(gè)表單,嵌套會(huì)使表單的行為不可預(yù)知
<fieldset>元素是一種方便的用于創(chuàng)建具有相同目的的小部件組的方式,出于樣式和語(yǔ)義目的
可以在<fieldset>開(kāi)口標(biāo)簽后加上一個(gè) <legend>元素來(lái)給<fieldset>標(biāo)上標(biāo)簽 <legend>的文本內(nèi)容正式地描述了<fieldset>里所含有部件的用途
一般來(lái)說(shuō),<fieldset>元素也可以用來(lái)對(duì)表單進(jìn)行分段
理想情況下,長(zhǎng)表單應(yīng)該在拆分為多個(gè)頁(yè)面,但是如果表單很長(zhǎng),卻必須在單個(gè)頁(yè)面上,那么將以不同的關(guān)聯(lián)關(guān)系劃分的分段,分別放在不同的fieldset里,可以提高可用性
<label>元素是為HTML表單小部件定義標(biāo)簽的正式方法
<label> 標(biāo)簽與<input> 通過(guò)他們各自的for 屬性和 id 屬性正確相關(guān)聯(lián)(label的for屬性和它對(duì)應(yīng)的小部件的id屬性)
<label for="name">Name:</label> <input type="text" id="name" name="user_name">
一個(gè)小部件可以嵌套在它的<label>元素中
<label for="name">
Name: <input type="text" id="name" name="user_name">
</label>
正確設(shè)置標(biāo)簽的另一個(gè)好處是可以在所有瀏覽器中單擊標(biāo)簽來(lái)激活相應(yīng)的小部件
這對(duì)于像文本輸入這樣的例子很有用,可通過(guò)點(diǎn)擊標(biāo)簽,和點(diǎn)擊輸入?yún)^(qū)效果一樣,來(lái)聚焦于它,這對(duì)于單選按鈕和復(fù)選框尤其有用——這種控件的可點(diǎn)擊區(qū)域可能非常小,設(shè)置標(biāo)簽來(lái)使它們可點(diǎn)擊區(qū)域變大是非常有用的
<p>元素也經(jīng)常被使用在構(gòu)造多個(gè)復(fù)選框或單選按鈕
4.原生表單部件
(1)通用屬性

(2)文本輸入框(type="text")
文本輸入框 <input>是最基本的表單小部件
這是一種非常方便的方式,可以讓用戶輸入任何類(lèi)型的數(shù)據(jù)
通用規(guī)范:
- 它們可以被標(biāo)記為
readonly(用戶不能修改輸入值)甚至是disabled(輸入值永遠(yuǎn)不會(huì)與表單數(shù)據(jù)的其余部分一起發(fā)送) - 它們可以有一個(gè)
placeholder; 這是文本輸入框中出現(xiàn)的文本,用來(lái)簡(jiǎn)略描述輸入框的目的 - 它們可以被限制在
size(框的物理尺寸) 和maxlength(可以輸入的最大字符數(shù)) - 如果瀏覽器支持的話,他們可以從拼寫(xiě)檢查中獲益
使用type屬性值被設(shè)置為text的<input>元素創(chuàng)建一個(gè)單行文本框(同樣的,如果不提供type屬性,text是默認(rèn)值)
單行文本框只有一個(gè)真正的約束:如果輸入帶有換行符的文本,瀏覽器會(huì)在發(fā)送數(shù)據(jù)之前刪除這些換行符
(3)E-mail地址框(type="email")
通過(guò)包括multiple屬性,它還可以讓用戶將多個(gè)電子郵件地址輸入相同的輸入(以逗號(hào)分隔)
當(dāng)使用 type時(shí), 用戶需要在框中輸入有效的電子郵件地址;任何其他內(nèi)容都會(huì)導(dǎo)致瀏覽器在提交表單時(shí)顯示錯(cuò)誤
(4)密碼框(type="password")
它不會(huì)為輸入的文本添加任何特殊的約束,但是它會(huì)模糊輸入到字段中的值(例如,用點(diǎn)或小行星),這樣它就不能被其他人讀取
這只是一個(gè)用戶界面特性;除非安全地提交表單,否則它會(huì)以明文發(fā)送,這不利于安全——惡意的一方可能會(huì)截獲數(shù)據(jù),竊取密碼、信用卡信息,或者提交的其他任何東西
保護(hù)用戶不受此影響的最佳方式是在安全連接上托管任何涉及表單的頁(yè)面(例如:https://……地址),使得數(shù)據(jù)在發(fā)送之前就已加密
(5)搜索框(type="search")
文本框和搜索框之間的主要區(qū)別是瀏覽器的樣式——通常,搜索框是渲染成圓角的,并且/可能給定一個(gè)“x”來(lái)清除輸入的值
然而,還有另外一個(gè)值得注意的特性:它們的值可以被自動(dòng)保存用來(lái)在同一站點(diǎn)上的多個(gè)頁(yè)面上自動(dòng)補(bǔ)全
(6)電話號(hào)碼欄(type="tel")
由于世界范圍內(nèi)各種各樣的電話號(hào)碼格式,這種類(lèi)型的字段不會(huì)對(duì)用戶輸入的值執(zhí)行任何限制(包括字母,等等)
這主要是在語(yǔ)義上的區(qū)分,盡管在一些設(shè)備上(特別是在移動(dòng)設(shè)備上),可能會(huì)出現(xiàn)一個(gè)不同的虛擬鍵盤(pán),更適合輸入電話號(hào)碼
(7)URL欄(type="url")
它為字段添加了特殊的驗(yàn)證約束,如果輸入無(wú)效的url,瀏覽器就會(huì)報(bào)告錯(cuò)誤
URL格式良好并不一定意味著它引用了一個(gè)實(shí)際存在的位置
(8)多行文本框
多行文本框?qū)V甘褂?<textarea>元素,而不是使用<input> 元素
textarea和常規(guī)的單行文本字段之間的主要區(qū)別是,允許用戶輸入包含硬換行符(即按回車(chē))的文本

<input>元素是一個(gè)空元素,這意味著它不能包含任何子元素另一方面,
<textarea>元素是一個(gè)常規(guī)元素,可以包含文本內(nèi)容的子元素
- 如果為
<input>元素定義一個(gè)默認(rèn)值,那么必須使用value屬性;另一方面,對(duì)于<textarea>元素,只需要將默認(rèn)的文本放在起始標(biāo)記和<textarea>的結(jié)束標(biāo)記之間 - 因?yàn)樗谋举|(zhì),
<textarea>元素只接受文本內(nèi)容;這意味著將任何HTML內(nèi)容放入<textarea>中都呈現(xiàn)為純文本內(nèi)容
(9)下拉內(nèi)容
一個(gè)選擇框是用<select>元素創(chuàng)建的,其中有一個(gè)或多個(gè)<option>元素作為子元素,每個(gè)元素都指定了其中一個(gè)可能的值
如果需要,可以使用selected屬性在所需的<option>元素上設(shè)置選擇框的默認(rèn)值---在頁(yè)面加載時(shí)會(huì)默認(rèn)選擇該選項(xiàng)<option>元素也可以嵌套在<optgroup>元素中,以創(chuàng)建視覺(jué)關(guān)聯(lián)的組值
<select id="groups" name="groups">
<optgroup label="fruits">
<option>Banana</option>
<option selected>Cherry</option>
<option>Lemon</option>
</optgroup>
<optgroup label="vegetables">
<option>Carrot</option>
<option>Eggplant</option>
<option>Potato</option>
</optgroup>
</select>
如果一個(gè)<option>元素設(shè)置了value屬性,那么當(dāng)提交表單時(shí)該屬性的值就會(huì)被發(fā)送
如果忽略了value屬性,則使用<option>元素的內(nèi)容作為選擇框的值
在<optgroup>元素中,label屬性顯示在值之前,但即使它看起來(lái)有點(diǎn)像一個(gè)選項(xiàng),它也不是可選的
默認(rèn)情況下,選擇框只允許用戶選擇一個(gè)值
通過(guò)將multiple屬性添加到<select>元素,可允許用戶通過(guò)操作系統(tǒng)提供的默認(rèn)機(jī)制來(lái)選擇幾個(gè)值
可以使用<datalist>元素來(lái)為表單小部件提供建議的、自動(dòng)完成的值,并使用一些<option>子元素來(lái)指定要顯示的值
然后使用list屬性將數(shù)據(jù)列表綁定到一個(gè)文本框(通常是一個(gè) <input> 元素)
<label for="myFruit">What's your favorite fruit?</label>
<input type="text" name="myFruit" id="myFruit" list="mySuggestion">
<datalist id="mySuggestion">
<option>Apple</option>
<option>Banana</option>
<option>Blackberry</option>
<option>Blueberry</option>
<option>Lemon</option>
<option>Lychee</option>
<option>Peach</option>
<option>Pear</option>
</datalist>
<datalist>元素版本小于10的IE中不受支持,同時(shí)在版本小于12的Safari中不受支持
(10)可選中項(xiàng):有兩種可選中項(xiàng):復(fù)選框和單選按鈕,只有在勾選時(shí)才發(fā)送它們的值
使用type屬性值為checkbox的 <input>元素來(lái)創(chuàng)建一個(gè)復(fù)選框
使用type屬性值為radio的 <input>元素來(lái)創(chuàng)建一個(gè)單選按鈕
(11)按鈕
在HTML表單中,有三種按鈕:
- Submit
將表單數(shù)據(jù)發(fā)送到服務(wù)器
對(duì)于<button> 元素, 省略 type 屬性 (或是一個(gè)無(wú)效的 type 值) 的結(jié)果就是一個(gè)提交按鈕. - Reset
將所有表單小部件重新設(shè)置為它們的默認(rèn)值 - Anonymous
沒(méi)有自動(dòng)生效的按鈕,但是可以使用JavaScript代碼進(jìn)行定制
<button>元素允許在它們的標(biāo)簽中使用HTML內(nèi)容,這些內(nèi)容被插入到打開(kāi)和關(guān)閉<button> 標(biāo)簽中
另一方面,<input>元素是空元素;它們的標(biāo)簽插入在value屬性中,因此只接受純文本內(nèi)容
使用<button>元素,可以有一個(gè)不同于按鈕標(biāo)簽的值(通過(guò)設(shè)置value中的屬性值)
這在IE 8之前的版本中是不可靠的
從技術(shù)上講,使用<button>元素或<input>元素定義的按鈕幾乎沒(méi)有區(qū)別
唯一值得注意的區(qū)別是按鈕本身的標(biāo)簽
在<input>元素中,標(biāo)簽只能是字符數(shù)據(jù),而在<button>元素中,標(biāo)簽可以是HTML,因此可以相應(yīng)地進(jìn)行樣式化
5.高級(jí)表單
(1)數(shù)字
用于數(shù)字的小部件是用type屬性設(shè)置為number<input>的元素創(chuàng)建的
這個(gè)控件看起來(lái)像一個(gè)文本框,但是只允許浮點(diǎn)數(shù),并且通常提供一些按鈕來(lái)增加或減少小部件的值
- 通過(guò)設(shè)置
min和max屬性來(lái)約束該值 - 通過(guò)設(shè)置
step屬性來(lái)指定增加和減少按鈕更改小部件的步進(jìn)值大小
(2)滑塊
滑塊是通過(guò)把<input>元素的type屬性值設(shè)置為range來(lái)創(chuàng)建的
正確配置滑塊是很重要的;為了達(dá)到這個(gè)目的,最好設(shè)置min、max和step屬性
滑塊的一個(gè)問(wèn)題是,它們不提供任何形式的視覺(jué)反饋,以了解當(dāng)前的值是什么
需要使用JavaScript來(lái)添加這一點(diǎn),但這相對(duì)來(lái)說(shuō)比較容易
在10以下的Internet Explorer版本中不支持range
(3)時(shí)間選擇器
所有日期和時(shí)間控制都可以使用min和max屬性來(lái)約束
警告——日期和時(shí)間窗口小部件仍然很不受支持
目前,Chrome、Edge和Opera都支持它們,但I(xiàn)E瀏覽器沒(méi)有支持,F(xiàn)irefox和Safari對(duì)這些都沒(méi)有太大的支持
(4)拾色器
一個(gè)顏色小部件是使用type屬性設(shè)置為值color<input>的元素創(chuàng)建的
(5)文件選擇器
要?jiǎng)?chuàng)建一個(gè)文件選擇器小部件,<input>元素的type屬性設(shè)置為file
被接受的文件類(lèi)型可以使用accept屬性來(lái)約束
選擇多個(gè)文件,那么可以通過(guò)添加multiple屬性來(lái)實(shí)現(xiàn)
(6)隱藏內(nèi)容
由于為了方便技術(shù)原因,有些數(shù)據(jù)是用表單發(fā)送的,但不顯示給用戶
要做到這一點(diǎn),可以在表單中添加一個(gè)不可見(jiàn)的元素
要做到這一點(diǎn),需要使用<input>將它的type屬性設(shè)置為hidden值
(7)圖像按鈕
當(dāng)用戶點(diǎn)擊它時(shí),它的行為就像一個(gè)提交按鈕(見(jiàn)上面)
圖像按鈕是使用type屬性值設(shè)置為image<input>的元素創(chuàng)建的
這個(gè)元素支持與<img>元素相同的屬性,和其他表單按鈕支持的所有屬性
如果使用圖像按鈕來(lái)提交表單,這個(gè)小部件不會(huì)提交它的值;相反,提交的是在圖像上單擊處的X和Y坐標(biāo)(坐標(biāo)是相對(duì)于圖像的,這意味著圖像的左上角表示坐標(biāo)0,0),坐標(biāo)被發(fā)送為兩個(gè)鍵/值對(duì):
X值鍵是name屬性的值,后面是字符串“.x”
Y值鍵是name屬性的值,后面是字符串“.y”
構(gòu)建“熱圖”的一種非常方便的方式
(8)進(jìn)度條
<progress>元素中的內(nèi)容用于不支持該元素的瀏覽器的回退,以及輔助技術(shù)對(duì)其朗讀
(9)儀表
- low 和 high 值范圍劃分為三個(gè)部分:
該范圍的較低部分是在min和low值(包括那些值)之間
該范圍的中間部分是在low和high值之間(不包括那些值)
該范圍的較高部分是在high和max值(包括那些值)之間 - optimum值定義了<meter>元素的最優(yōu)值
在與htmlattrxref(“l(fā)ow”、“meter”)和high值的聯(lián)合中,它定義了該范圍的哪個(gè)部分是優(yōu)先的:
如果optimum值在較低的范圍內(nèi),則較低的范圍被認(rèn)為是首選項(xiàng),中等范圍被認(rèn)為是一般的,而較高的范圍被認(rèn)為是最壞的部分
如果optimum值在該范圍的中等部分,則較低的范圍被認(rèn)為是一個(gè)一般的,中等范圍被認(rèn)為是優(yōu)先的部分,而較高的范圍也被認(rèn)為是平均值
如果optimum值在較高的范圍內(nèi),則較低的范圍被認(rèn)為是最壞的部分,中等范圍被認(rèn)為是一般的部分,較高的范圍被認(rèn)為是優(yōu)先的部分
所有實(shí)現(xiàn)<meter>元素的瀏覽器都使用這些值來(lái)改變米尺的顏色
如果當(dāng)前值位于該范圍的優(yōu)先部分,則該條是綠色的
如果當(dāng)前值位于該范圍的平均部分,則該條是黃色的
如果當(dāng)前值處于最糟糕的范圍,則該條是紅色的
<meter min="0" max="100" value="75" low="33" high="66" optimum="50">75</meter>
<meter>元素中的內(nèi)容是不支持該元素的瀏覽器的回退,以及輔助技術(shù)對(duì)其發(fā)出的聲音
對(duì)進(jìn)度條和儀表的支持是相當(dāng)不錯(cuò)的,在Internet Explorer中沒(méi)有支持,但是其他瀏覽器都可以很好的支持它
6.樣式化HTML表單
在1995年左右的Web早期,表單組件(或控件)在 HTML 2規(guī)范中被添加到HTML
由于表單組件的復(fù)雜性,實(shí)現(xiàn)者選擇依靠底層操作系統(tǒng)來(lái)管理和渲染它們
有些元素根本不能用應(yīng)用CSS樣式
這些包括:所有高級(jí)用戶界面小部件,如范圍,顏色或日期控件; 和所有下拉小部件,包括<select>, <option>, <optgroup>和<datalist> 元素
文件選擇器小部件也被稱為不可樣式化
新的<progress>和<meter> 元素也屬于這個(gè)類(lèi)別
搜索框是唯一一種應(yīng)用CSS樣式有點(diǎn)棘手的文本字段
在基于WebKit的瀏覽器(Chrome,Safari等)上,必須使用-webkit-appearance專有屬性來(lái)調(diào)整它
為了讓form表單的外觀和其他內(nèi)容保持一致,可在樣式表中增加以下內(nèi)容:
button, input, select, textarea {
font-family : inherit;
font-size : 100%;
}
因?yàn)槊總€(gè)小部件都有自己的邊框,填充和邊距的規(guī)則
所以如果想給幾個(gè)不同的小部件相同的大小,必須使用box-sizing 屬性
input, textarea, select, button {
width : 150px;
margin: 0;
-webkit-box-sizing: border-box; /* For legacy WebKit based browsers */
-moz-box-sizing: border-box; /* For legacy (Firefox <29) Gecko based browsers */
box-sizing: border-box;
}
添加outline 屬性非常重要,這樣可以移除由某些瀏覽器添加的默認(rèn)高亮效果:
單行文本需要一些調(diào)整才能在 Internet Explorer 中渲染良好
Internet Explorer 沒(méi)有基于字體的自然高度來(lái)定義文本域的高度(而這是所有其他瀏覽器都有的行為)
為了修正這個(gè)問(wèn)題,我們需要給域添加一個(gè)確定的高度,像下面這樣:
input {
height: 2.5em; /* for IE */
vertical-align: middle; /* This is optional but it makes legacy IEs look better */
}
<textarea> 元素默認(rèn)地被渲染成一個(gè)塊級(jí)元素
這里有重要地兩點(diǎn)是 resize 和 overflow 屬性
因?yàn)槲覀兊脑O(shè)計(jì)是一個(gè)固定大小的設(shè)計(jì),所以使用 resize 屬性來(lái)防止用戶調(diào)整我們的多行文本域的大小
overflow 屬性是用來(lái)讓域在不同的瀏覽器上渲染得更一致
一些瀏覽器默認(rèn)值為 auto,而一些將默認(rèn)值設(shè)為 scroll
在例子中,最好確定每個(gè)瀏覽器都使用 auto
textarea {
display : block;
padding : 10px;
margin : 10px 0 0 -10px;
width : 340px;
height : 360px;
resize : none;
overflow: auto;
}
7.高級(jí)設(shè)計(jì)表單樣式

8.表單數(shù)據(jù)校驗(yàn)
表單校驗(yàn) —— 向 Web 應(yīng)用輸入數(shù)據(jù)時(shí),應(yīng)用會(huì)驗(yàn)證輸入的數(shù)據(jù)是否是正確的
如果驗(yàn)證通過(guò),應(yīng)用允許提交這些數(shù)據(jù)到服務(wù)器并儲(chǔ)存到數(shù)據(jù)庫(kù)中(通常情況下),如果驗(yàn)證未通過(guò),則 Web 應(yīng)用會(huì)提示有錯(cuò)誤的數(shù)據(jù),并且一般都會(huì)明確的告訴錯(cuò)誤發(fā)生在哪里
表單校驗(yàn)可以通過(guò)許多不同的方式實(shí)現(xiàn)
三個(gè)最主要的原因:
- 我們希望以正確的格式獲取到正確的數(shù)據(jù) —— 如果我們的用戶數(shù)據(jù)以不正確的格式存儲(chǔ),或者他們沒(méi)有輸入正確的信息/完全省略信息,我們的應(yīng)用程序?qū)o(wú)法正常運(yùn)行
- 我們希望保護(hù)我們的用戶 ——強(qiáng)制用戶輸入安全的密碼,有利于保護(hù)他們的賬戶信息
- 我們希望保護(hù)我們自己 —— 惡意用戶有很多通過(guò)濫用應(yīng)用中缺乏保護(hù)的表單破壞應(yīng)用的方法(具體請(qǐng)參見(jiàn)網(wǎng)站安全)
不同的表單校驗(yàn):
客戶端校驗(yàn)發(fā)生在瀏覽器端,表單數(shù)據(jù)被提交到服務(wù)器之前,這種方式相較于服務(wù)器端校驗(yàn)來(lái)說(shuō),用戶體驗(yàn)更好,它能實(shí)時(shí)的反饋用戶的輸入校驗(yàn)結(jié)果,這種類(lèi)型的校驗(yàn)可以進(jìn)一步細(xì)分成下面這些方式:
JavaScript 校驗(yàn),這是可以完全自定義的實(shí)現(xiàn)方式;
HTML5 內(nèi)置校驗(yàn),這不需要 JavaScript ,而且性能更好,但是不能像JavaScript那樣可自定義
服務(wù)器端校驗(yàn)則是發(fā)生在瀏覽器提交數(shù)據(jù)并被服務(wù)器端程序接收之后 —— 通常服務(wù)器端校驗(yàn)都是發(fā)生在將數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)之前,如果數(shù)據(jù)沒(méi)通過(guò)校驗(yàn),則會(huì)直接從服務(wù)器端返回錯(cuò)誤消息,并且告訴瀏覽器端發(fā)生錯(cuò)誤的具體位置和原因,服務(wù)器端校驗(yàn)不像客戶端校驗(yàn)?zāi)菢佑泻玫挠脩趔w驗(yàn),因?yàn)樗钡秸麄€(gè)表單都提交后才能返回錯(cuò)誤信息
但是服務(wù)器端校驗(yàn)是應(yīng)用對(duì)抗錯(cuò)誤/惡意數(shù)據(jù)的最后防線,在這之后,數(shù)據(jù)將被持久化至數(shù)據(jù)庫(kù)
當(dāng)今所有的服務(wù)端框架都提供了數(shù)據(jù)校驗(yàn)與清潔功能(讓數(shù)據(jù)更安全)
在真實(shí)的項(xiàng)目開(kāi)發(fā)過(guò)程中,開(kāi)發(fā)者一般都傾向于使用客戶端校驗(yàn)與服務(wù)器端校驗(yàn)的組合校驗(yàn)方式以更好的保證數(shù)據(jù)的正確性與安全性
(1)required屬性
required屬性 — 如果要使輸入成為必需的,則可以使用此屬性標(biāo)記元素
當(dāng)設(shè)置此屬性時(shí),如果輸入為空,該表單將不會(huì)提交(并將顯示錯(cuò)誤消息),輸入也將被視為無(wú)效
(2)正則表達(dá)式
校驗(yàn)功能是 pattern 屬性, 以 Regular Expression 作為 value 值. 正則表達(dá)式 (regex) 是一個(gè)可以用來(lái)匹配文本字符串中字符的組合的模式,所以它們是理想的表單校驗(yàn)器,也可以支持 JavaScript 中許多其它的用途
(3)限制輸入的長(zhǎng)度
所有文本框 (<input> 或 <textarea>) 都可以使用minlength 和 maxlength 屬性來(lái)限制長(zhǎng)度. 如果輸入的字段長(zhǎng)度小于 minlength 的值或大于 maxlength 值則無(wú)效
在數(shù)字條目中 (i.e. <input type="number">), 該 min 和 max 屬性同樣提供校驗(yàn)約束.如果字段的值小于min 屬性的值或大于 max 屬性的值,該字段則無(wú)效
(4)自定義錯(cuò)誤信息
在JavaScript 中, 調(diào)用 setCustomValidity() 方法:
//HTML
<form>
<label for="mail">I would like you to provide me an e-mail</label>
<input type="email" id="mail" name="mail">
<button>Submit</button>
</form>
//JS
var email = document.getElementById("mail");
email.addEventListener("input", function (event) {
if (email.validity.typeMismatch) {
email.setCustomValidity("I expect an e-mail, darling!");
} else {
email.setCustomValidity("");
}
});
(5)使用JS校驗(yàn)表單
詳見(jiàn)文檔
表單校驗(yàn)注意事項(xiàng):
- 顯示明確的錯(cuò)誤消息
- 放寬輸入格式限制
- 指出錯(cuò)誤發(fā)生的位置(特別是在大型表單中)
9.發(fā)送表單數(shù)據(jù)
<form>元素定義了如何發(fā)送數(shù)據(jù)
它的所有屬性都是為了配置當(dāng)用戶點(diǎn)擊提交按鈕時(shí)發(fā)送的請(qǐng)求
兩個(gè)最重要的屬性是action和method
action 屬性定義了發(fā)送數(shù)據(jù)要去的位置
它的值必須是一個(gè)有效的URL
如果沒(méi)有提供此屬性,則數(shù)據(jù)將被發(fā)送到包含這個(gè)表單的頁(yè)面的URL
method屬性定義了如何發(fā)送數(shù)據(jù)
HTTP協(xié)議提供了幾種執(zhí)行請(qǐng)求的方法;HTML表單數(shù)據(jù)可以通過(guò)許多不同的方法進(jìn)行數(shù)據(jù)傳輸,其中最常見(jiàn)的是GET方法和POST方法
(1)發(fā)送文件
用HTML表單發(fā)送文件是一個(gè)特殊的例子
文件是二進(jìn)制數(shù)據(jù)——或者被認(rèn)為是這樣的——而所有其他數(shù)據(jù)都是文本數(shù)據(jù)
由于HTTP是一種文本協(xié)議,所以處理二進(jìn)制數(shù)據(jù)有特殊的要求
enctype 屬性允許指定在提交表單時(shí)所生成的請(qǐng)求中的Content-Type的HTTP數(shù)據(jù)頭的值
這個(gè)數(shù)據(jù)頭非常重要,因?yàn)樗嬖V服務(wù)器正在發(fā)送什么樣的數(shù)據(jù)
默認(rèn)情況下,它的值是application/x-www-form-urlencoded
它的意思是:“這是已編碼為URL參數(shù)的表單數(shù)據(jù)”
要發(fā)送文件,需要額外的三個(gè)步驟:
將method屬性設(shè)置為POST,因?yàn)槲募?nèi)容不能放入U(xiǎn)RL參數(shù)中
將enctype的值設(shè)置為multipart/form-data,因?yàn)閿?shù)據(jù)將被分成多個(gè)部分,每個(gè)文件單獨(dú)占用一個(gè)部分,表單正文中包含的文本數(shù)據(jù)(如果文本也輸入到表單中)占用一個(gè)部分
包含一個(gè)或多個(gè)File picker小部件,允許用戶選擇將要上傳的文件
(2)常見(jiàn)安全問(wèn)題
跨站腳本(XSS)和跨站點(diǎn)請(qǐng)求偽造(CSRF)是常見(jiàn)的攻擊類(lèi)型,它們發(fā)生在將用戶發(fā)送的數(shù)據(jù)顯示給這個(gè)用戶或另一個(gè)用戶時(shí)
- XSS允許攻擊者將客戶端腳本注入到其他用戶查看的Web頁(yè)面中
攻擊者可以使用跨站點(diǎn)腳本攻擊的漏洞來(lái)繞過(guò)諸如同源策略之類(lèi)的訪問(wèn)控制 - CSRF攻擊類(lèi)似于XSS攻擊,因?yàn)樗鼈円韵嗤姆绞介_(kāi)始攻擊——向Web頁(yè)面中注入客戶端腳本——但它們的目標(biāo)是不同的CSRF攻擊者試圖將權(quán)限升級(jí)到特權(quán)用戶(比如站點(diǎn)管理員)的級(jí)別,以執(zhí)行他們不應(yīng)該執(zhí)行的操作(例如,將數(shù)據(jù)發(fā)送給一個(gè)不受信任的用戶)
XSS攻擊利用用戶對(duì)web站點(diǎn)的信任,而CSRF攻擊則利用網(wǎng)站對(duì)其用戶的信任 - SQL 注入是一種試圖在目標(biāo)web站點(diǎn)使用的數(shù)據(jù)庫(kù)上執(zhí)行操作的攻擊類(lèi)型
這通常包括發(fā)送一個(gè)SQL請(qǐng)求,希望服務(wù)器能夠執(zhí)行它(通常發(fā)生在應(yīng)用服務(wù)器試圖存儲(chǔ)由用戶發(fā)送的數(shù)據(jù)時(shí))
HTTP數(shù)據(jù)頭注入和電子郵件注入,出現(xiàn)在當(dāng)應(yīng)用程序基于表單上用戶的數(shù)據(jù)輸入構(gòu)建HTTP頭部或電子郵件時(shí)
10.構(gòu)建表單小工具
(1) tabIndex 屬性可以確保原生組件將永遠(yuǎn)不會(huì)獲得焦點(diǎn),而且還可以確保當(dāng)用戶用戶使用鍵盤(pán)和鼠標(biāo)時(shí),自定義組件能夠獲得焦點(diǎn)
(2)ARIA 使用的關(guān)鍵屬性是 role 屬性
role 屬性接受一個(gè)值,該值定義了一個(gè)元素的用途
每個(gè) role 定義了它自己的需求和行為
ARIA定義了默認(rèn)應(yīng)用于標(biāo)準(zhǔn) HTML 標(biāo)記的角色
例如,<table> 元素與角色 grid 相匹配,而 <ul> 元素與角色 list 相匹配
由于我們使用了一個(gè) <ul> 元素,我們想要確保我們組件的 listbox 角色能替代 <ul> 元素的list 角色
presentation角色被設(shè)計(jì)成來(lái)表示一個(gè)元素沒(méi)有特殊的含義,并且僅僅用于提供信息
aria-selected 屬性被用來(lái)標(biāo)記當(dāng)前被選中的選項(xiàng);這可以讓輔助技術(shù)告知用戶當(dāng)前的選項(xiàng)是什么
通過(guò) JavaScript 動(dòng)態(tài)地使用該屬性,每當(dāng)用戶選擇一個(gè)選項(xiàng)時(shí)標(biāo)記選中的選項(xiàng)
11.使用JS提交表單
三種方式發(fā)送表單數(shù)據(jù):
- 構(gòu)建 XMLHttpRequest,XMLHttpRequest 是進(jìn)行 HTTP 請(qǐng)求的最安全和最可靠的方式
- 使用 XMLHttpRequest 和 the FormData object(表單數(shù)據(jù)對(duì)象)
- 在隱藏的iframe中構(gòu)建DOM,最古老的異步發(fā)送表單數(shù)據(jù)方法是用 DOM API 構(gòu)建表單,然后將其數(shù)據(jù)發(fā)送到隱藏的 <iframe>