表單為頁(yè)面的主要組成部分,其中包含許多的表單控件。用戶通過(guò)控件提供數(shù)據(jù)并提交給服務(wù)器,服務(wù)器則做出相應(yīng)的處理。而編寫一個(gè)正常工作的表單需要三個(gè)部分:
構(gòu)建表單
<form>
<p><label>姓名:<input></label></p>
<p><label>電話:<input type="tel"></label></p>
<p><label>郵箱:<input type="email"></label></p>
<fieldset>
<legend> 披薩大小 </legend>
<label><input type="radio" name="size"> 小 </label>
<label><input type="radio" name="size"> 中 </label>
<label><input type="radio" name="size"> 大 </label>
</fieldset>
<fieldset>
<legend> 披薩配料 </legend>
<label><input type="checkbox"> 熏肉 </input></label>
<label><input type="checkbox"> 奶酪 </input></label>
<label><input type="checkbox"> 洋蔥 </input></label>
<label><input type="checkbox"> 蘑菇 </input></label>
</fieldset>
<p><label>配送時(shí)間:<input type="time" min="11:00" max="2100" step="900"></label></p>
<p><button>提交訂單</button></p>
</form>
服務(wù)器處理
提供接口地址(例如,https://pizza.example.com/order
,數(shù)據(jù)格式(application/x-www-form-urlencoded
),還是接受的參數(shù)信息(custname、custtel、custemail、size、topping、delivery)。
數(shù)據(jù)命名需在表單控件中注明。
配置表單
<form action="https://pizza.example.com/order" method="post" enctype="application/x-www-form-urlencoded">
<p><label>姓名:<input name="custname"></label></p>
<p><label>電話:<input type="tel" name="custtel"></label></p>
<p><label>郵箱:<input type="email" name="custemail"></label></p>
<fieldset>
<legend> 披薩大小 </legend>
<label><input type="radio" name="size" value="small"> 小 </label>
<label><input type="radio" name="size" value="medium"> 中 </label>
<label><input type="radio" name="size" value="large"> 大 </label>
</fieldset>
<fieldset>
<legend> 披薩配料 </legend>
<label><input type="checkbox"> 熏肉 </input></label>
<label><input type="checkbox"> 奶酪 </input></label>
<label><input type="checkbox"> 洋蔥 </input></label>
<label><input type="checkbox"> 蘑菇 </input></label>
</fieldset>
<p><label>配送時(shí)間:<input type="time" min="11:00" max="2100" step="900"></label></p>
<p><button>提交訂單</button></p>
</form>
用戶所有提交的信息需在提交服務(wù)器前對(duì)其進(jìn)行驗(yàn)證從而提高用戶體驗(yàn)。
NOTE:表單驗(yàn)證 使用 require
來(lái)強(qiáng)制用戶填寫相應(yīng)的信息。
form 元素為構(gòu)建表單中最重要的元素。
<form novalidate name="pizza" target="abc" method="post" autocomplete="off" accept-charset="utf-8" action="http://pizza.example.com/order" enctype="application/x-www-form-urlencoded">
其對(duì)應(yīng)的信息則可以視為
字段 | 值 |
---|---|
noValidate | true |
target | abc |
method | post |
acceptCharset | utf-8 |
action | http://pizza.example.com/order |
enctype | application/x-www-form-urlencoded |
name | pizza |
autocomplete | off |
NOTE:前六項(xiàng)為表單提交相關(guān)的信息。
name
屬性:可以用于獲取表單節(jié)點(diǎn)元素。var pizzaForm = document.forms.pizza;
autocomplete
屬性:有兩個(gè)值 on
與 off
,在設(shè)置為 on
時(shí),可以自動(dòng)對(duì)輸入框進(jìn)行補(bǔ)全(之前提交過(guò)的輸入值,下圖左)。NOTE:在已經(jīng)設(shè)置 autocomplete="off"
時(shí)依然出現(xiàn)提示框,大多數(shù)情況為瀏覽器設(shè)置的自動(dòng)補(bǔ)全(可以強(qiáng)制關(guān)閉,需要時(shí)請(qǐng)搜索對(duì)應(yīng)的解決方案)。
elements
屬性:為一個(gè)動(dòng)態(tài)節(jié)點(diǎn)集合(更具 DOM 的變化進(jìn)行變化),其用于歸結(jié)該表單的子孫表單控件(除圖標(biāo)按鈕外 <input type="image>"
):
此外還有歸屬于該表單的空間(依舊圖片按鍵除外)代碼如下所示。
<form id="a">
</form>
<label><input name="null" form="a"></label>
length
屬性:等價(jià)于 elements.length
來(lái)用于描述表單內(nèi)節(jié)點(diǎn)集合的個(gè)數(shù)。<form name="test">
<input name="a">
<input name="b">
</form>
選取 name="a"
的控件可以使用下面的方法:
testForm.elements[0];
testForm.elements['a'];
// 操作 Form 表單的屬性
testForm[0];
testForm['a'];
form[name]
通過(guò)名稱作為索引時(shí)有如下特點(diǎn):
id
或者 name
為指定名稱的表單空間(圖標(biāo)按鍵除外)id
為指定名稱的 img
元素(入下面代碼所示)id
或者 name
如何變化,只有節(jié)點(diǎn)存在則均可使用原名稱來(lái)繼續(xù)獲取改節(jié)點(diǎn)。無(wú)指定名稱索引范例
<form name="test">
<img id="a" src="sample.png">
</form>
testForm['a']; // 取得的便是 id 為 a 的圖片元素
更新名稱,依然可以獲取節(jié)點(diǎn)范例
<form name="test">
<input name="a">
</form>
// 第一步
testForm['a'];
// 或者
testForm.elements['a'];
// 第二步
testForm['a'].name = 'b';
form
元素也提供了一些接口便于對(duì)其進(jìn)行操作 reset()
submit()
checkValidity()
。
可以重置(reset)的元素有下面的幾種:
當(dāng)觸發(fā)表單 reset
事件時(shí)可使用阻止該事件的默認(rèn)行為來(lái)取消重置。而且元素重置時(shí)將不會(huì)再次觸發(fā)元素上的 change
與 input
事件。
<label for="textId" form="formId">
字段 | 值 |
---|---|
htmlFor | textId |
control | HTMLElement#textId |
form | HTMLFormElement#formId |
htmlFor
屬性:用于關(guān)聯(lián)表單控件的激活行為(可使點(diǎn)擊 label
與點(diǎn)擊表單控件的行為一致),可關(guān)聯(lián)的元素有下列(hidden
除外):
自定義文件提交控件樣式
control
屬性:如果指定了 for
屬性則指定該for
屬性對(duì)于 id
的可關(guān)聯(lián)元素。如果沒(méi)有指定 for
屬性則為第一個(gè)可關(guān)聯(lián)的子孫元素。可關(guān)聯(lián)的元素 (只讀屬性不可在程序中直接賦值修改)
- form
屬性:修改關(guān)聯(lián)元素所歸屬的表單則可以修改元素的 form
屬性為帶關(guān)聯(lián)表單Id(元素中對(duì)于的for
屬性也應(yīng)該做對(duì)應(yīng)的修改)。//這里有一點(diǎn)小問(wèn)題,更改form屬性之后label并不能自動(dòng)綁定到新表單對(duì)應(yīng)的元素上
label.setAttribute('form', 'newFormId');
<input type="text">
type
屬性:可用于控制控件的外觀以及數(shù)據(jù)類型(默認(rèn)為 text
),在不同的瀏覽器不同數(shù)據(jù)類型有不同的展示效果。本地圖片預(yù)覽示例
所需技術(shù)點(diǎn)(HTMLInputElement屬性)
<input type="file" accept="image/*" multiple>
file.addEventListener(
'change', function(event){
var files = Array.prototype.slice.call(
event.target.files, 0
);
files.forEach(function(item){
files2dataurl(item,function(url){
var image = new Image();
parent.appendChild(image);
image.src = url;
});
});
}
);
function file2dataurl(file, callback) {
if (!window.FileReader) {
throw 'Browser not support File API !';
}
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(event) {
callback(event.target.result);
};
}
NOTE:accept
所支持的格式有 audio/*
video/*
image/*
以及不帶;
的 MINE Type 類型和 .
開頭的文件名后綴的文件。多個(gè)文件類型可以使用,
分隔。
指定選項(xiàng)列表中選擇需要的選項(xiàng)。
主要的三個(gè)子標(biāo)簽 select
、optgroup
(用于選項(xiàng)分組)、option
。
select
具有的屬性和方法如下:
optgroup
所具有的屬性和方法:
option
所具有的屬性和方法:
創(chuàng)建選項(xiàng)
document.createElement('option')
// 或者
new Option([text[, value[, defaultSelected[, selected]]]])
添加選項(xiàng)
var option = new Option('sample');
opt.insertAdjacentElement(option, '參照元素');
// 或者
select.add(option, '參照元素')
刪除選項(xiàng)
opt.parentNode.removeChild(option);
// 或者使用它的索引將其刪除
select.remove(2);
所需知識(shí)點(diǎn):
<form name="course">
<select name="chapter">
<option>Select0</option>
</select>
<select name="section">
<option>Select1</option>
</select>
</form>
var chapters = {
{text: 1, value: 1},
{text: 2, value: 2}
};
var sections = {
1: [{
text:1.1, value: 1.1
}, {
text:1.2, value: 1.2
}],
2:[{
text:2.1, value:2.1;
}]
};
function fillSelect(select, list) {
for(var i = select.length; i > 0; i--) {
select.remove(i);
}
list.forEach(function(data){
var option = new Option(data.text, data.value);
select.add(option);
})
}
fileSelect(chapterSelect, chapters);
chapterSelect.addEventListener(
'change', function(event) {
var value = event.target.value,
list = sections[value] || [];
fillSelect(sectionSelect, list);
}
);
textarea
具有的屬性和方法如下:
forward
backward
)表示選擇區(qū)域,對(duì)于 input
元素同樣有效。
selectionDirection
主要是用于在使用 SHIFT 鍵與方向鍵組合選取時(shí)的選取方向。設(shè)置為 forward
時(shí)選取移動(dòng)的方向?yàn)?nbsp;selectionEnd
設(shè)置為 backward
時(shí)移動(dòng)方向?yàn)?nbsp;selectionStart
。
@輸入提示示例
所需知識(shí)點(diǎn):
textarea.addEventListener(
'input', function(event) {
var target = event.target,
cursor = target.selectionStart;
if(target.value.charAt(cursor-1) === '@') {
doShowAtList(functi=on(name){
var end = cursor + name.length;
target.setRangeText(
name, cursor, end, 'end'
);
});
}
}
);
可以被驗(yàn)證的元素如下所示:】
以下情況不可以做驗(yàn)證
驗(yàn)證涉及到以下的以下屬性,在每一個(gè)可以驗(yàn)證的元素上均可以調(diào)用對(duì)于的屬性或通過(guò)接口進(jìn)行操作:
自定義異常范例
涉及到的知識(shí)點(diǎn):
<form action="./api" method="post">
<label>Name: <input name="username" required></label>
<button>submit</button>
</form>
input.addEventListener(
'invalid', function(event){
var target = event.target;
if (target.validity.valueMissing) {
target.setCustomValidity('Name is missing');
}
}
)
禁止驗(yàn)證范例
使用 form
中 novalidate
屬性來(lái)禁止表單提交的驗(yàn)證。
<form action="./api" method="post" novalidate>
<label>Mobile: <input name="mobile" type="number"></label>
<button>submit</button>
</form>
在操作過(guò)程中通過(guò)控件的操作來(lái)提交表單(敲擊回車來(lái)提交表單),其需要滿足以下的條件:
text
search
url
email
password
date
time
number
的 input
元素提交過(guò)程分為兩個(gè)階段,第一個(gè)階段是更具表單 enctype 指定的值構(gòu)建要提交的數(shù)據(jù),第二個(gè)階段是使用指定的方法(method)發(fā)送數(shù)據(jù)到 action
指定的目標(biāo)。
構(gòu)建提交數(shù)據(jù),從可提交元素中提取數(shù)據(jù)組成指定數(shù)據(jù)結(jié)構(gòu)過(guò)程(可提交元素有 button
input
keygen
object
select
textarea
)
編碼方式(enctype)所支持的形式:
&
分隔的鍵值對(duì))特殊案例一
當(dāng)一個(gè)表單元素 name="isindex"
并且 type="text"
而且滿足如下要求時(shí):
則提交時(shí)只發(fā)送 value 值,不包含 name。
<form action="./api" method="post">
<input name="isindex">
<input name="a">
<button>submit</button>
</form>
特殊案例二
當(dāng) name="_charset_"
并且類型為 hidden
時(shí),而且滿足如下要求時(shí):
value
值則提交時(shí) value
自動(dòng)使用當(dāng)前提交的字符集填充。
form.submit()
可以通過(guò)調(diào)用接口submit()
直接提交表單,在提交表單時(shí)均會(huì)觸發(fā)一個(gè) onsubmit
表單提交事件,在這個(gè)事件中 women 可以做下面的事件:
form.addEventListener(
'submit', function(event) {
var notValid = false;
var elements = event.target.elements;
// 自定義驗(yàn)證
if (notValid) {
// 取消提交
event.preventDefault();
}
}
)
無(wú)刷新表單提交范例
常用的方式是通過(guò) AJAX 進(jìn)行實(shí)現(xiàn),這里我們使用 iframe 來(lái)做中介代理實(shí)現(xiàn)。
所需知識(shí)點(diǎn):
<iframe name="targetFrame" class="f-hidden" style="display:none" id="result">
<form action="./api" method="post" target="targetFrame">
<input name="isindex">
<input name="a">
<button>submit</button>
</form>
var frame = document.getElementById('result');
frame.addEventListener(
'load', function(event) {
try {
var result = JSON.parse(
frame.contentWindow.document.body.textContent
);
// 還原登陸按鈕狀態(tài)
disabledSubmit(false);
// 識(shí)別登陸結(jié)果
if (result.code === 200) {
showMessage('j-suc', 'success');
form.reset();
}
} catch(ex) {
// 忽略操作
}
}
)
首先需要知道服務(wù)器端登陸接口的相關(guān)信息,如下所示:
描述 | 數(shù)據(jù)信息 |
---|---|
請(qǐng)求地址 | /api/login |
請(qǐng)求參數(shù) | telephone 手機(jī)號(hào)碼; password 密碼 MD5 加密 |
返回結(jié)果 | code 請(qǐng)求狀態(tài); result 請(qǐng)求數(shù)據(jù)結(jié)果 |
var form = document.forms.loginForm;
var message = document.getElementById('message');
// 通用邏輯封裝
function showMessage(class, message) {
if(!class) {
message.innerHTML = "";
message.classList.remove('j-suc');
message.classList.remove('j-err');
} else {
message.innerHTML = message;
message.classList.add(class);
}
}
function invalidInput (node, message) {
showMessage('j-err', message);
node.classList.add('j-err');
node.focus();
}
function clearInvalid(node){
showMessage();
node.classList.remove('j-err');
}
function disabledSubmit(disabled) {
form.loginBtn.disabled = !!disabled;
var method = !disabled ? 'remove' : 'add';
form.loginBtn.classList[method]('j-disabled');
}
// 驗(yàn)證手機(jī)號(hào)碼(系統(tǒng)自帶方法)
form.telephone.addEventListener(
'invalid', function(event) {
event.preventDefault();
invalidInput(form.telephone, 'invalid mobile number');
}
);
// 驗(yàn)證密碼
form.addEventListener(
'submit', function(event) {
var input = form.password;
var password = input.value;
errorMessage = '';
if (password.length < 6) {
errorMessage = 'password less than 6 char';
} else if (!/\d./test(password) || !/[a-z]/i.test(password)) {
errorMessage = 'password must contains number and letter'
}
if (!!errorMessage) {
event.preventDefault();
invalidInput(input, errorMessage);
return;
}
// 提交表單代碼
// ...
}
);
// 提交表單
form.addEventListener(
'submit', function(event){
input.value = md5(password);
disabledSubmit(true);
}
);
// 狀態(tài)恢復(fù)
form.addEventListener(
'focus', function(event) {
// 錯(cuò)誤還原
clearInvalid(event.target);
// 還原登陸按鈕狀態(tài)
disabledSubmit(false);
}
)
更多建議: