form表單那點事兒(下) 進階篇
上一篇主要溫習了一下form表單的屬性和表單元素,這一片主要講解用JavaScript如何操作form。
目錄:
表單操作
技巧
表單操作
取值
用JavaScript操作表單,免不了會有取值賦值操作,比如有以下表單:
<form id='form0'></form>
<form action="/login" method="post" target="blank" id='form1'>
<input type="text" name='user_name'> <!--field 0-->
<input type="email" name='user_email'> <!--field 1-->
<select name='user_phone'> <!--field 2-->
<option value='1'>13333333331</option>
<option value='2'>13333333332</option>
<option value='3'>13333333333</option>
</select>
<input type="text" name='form0_user_phone' form='form0'> <!--field 3-->
<button type='submit' form='form0'>預覽</button> <!--field 4-->
<button type='submit'>提交</button> <!--field 5-->
</form>
用JavaScript獲取表單的屬性值,或者表單字段的值,可以直接通過 elem.name
的方式
alert(form1.action); => '/login'
alert(form1.method); => 'post'
alert(form1.user_name.value) => ''
而要獲取表單中的字段,則通過:
// 屬於本表單元素nodelist類數組,如果通過form屬性指定到其他表單,不會算作本表單元素,下面獲取到的元素是field 0,field 1,field 2,field 5
console.log(form1.elements); => [<input>...,...,...</button>]
// 屬於本表單元素個數,如果通過form屬性指定到其他表單,不會算作本表單元素
console.log(form1.length); => 4
// nodelist中下標為2的表單元素
console.log(form1[1]); => <input type="email" name='user_email'>
// 表單中 name='user_name' 的元素,有同名的字段則返回一個nodelst類數組
console.log(form1['user_name']); => <input type="text" name='user_name'> 或 nodelist
// 獲取表單全部內容,詳情見下面的 “提交” 條目
jQuery('#form1').serialize(); => user_name=&user_email=&user_phone=13333333331
jQuery('#form1').serializeArray(); => [] 一個數組,里面是每個字段的鍵值對
new FormData(form1) => 沒有返回值
賦值
表單本身的屬性可以通過JavaScript賦值,比如 action
, method
, target
等。例如
// 把表單提交到 "/signIn"
form1.action = '/signIn';
// 修改表單提交方式為 "GET"
form1.method = 'GET';
而給表單元素賦值,則是通過 elem.value
的方式,例如
// 將user_name的值設定為 "hello world"
form1.user_name.value = "hello world";
// 選中select中值為2的option
form1.user_phone.value = 2;
重置
可以通過html或者JavaScript的方式把表單值重置為頁面初始的樣子。
html方式為點擊 type='reset'
的 input
或 button
。
JavaScript的方式為 form1.reset()
。
如果表單中應用了第三方UI庫如 select2
,重置后還需要手動觸發表單元素的change事件,以觸發第三方庫更新UI。
常用的方式是:
form1.reset();
$(form1.user_phone).change();
校驗
傳統校驗
傳統的表單校驗方式是通過監聽的 submit
事件或是表單字段的 input
, focus
, blur
, change
事件,去觸發JavaScript中指定的校驗規則,來確定表單是提交還是拒絕提交。
html5校驗
步入html5時代之后,可以僅通過html本身完成表單提交前的校驗工作。方式是給表單字段加上 required
和 pattern
屬性,
required
是告訴瀏覽器這個字段需要校驗,而 pattern
則指定一個正則表達式形式的校驗規則。在表單提交時,瀏覽器會自動進行一系列的校驗工作,沒有通過校驗的表單是無法提交到服務器的。
在表單提交之前,可以通過 form.checkValidity()
方法,這個方法會返回一個布爾值回饋整個表單是否通過了校驗規則。
比較知名的表單校驗插件是 jquery-validation 。
提交
提交規則
提交表單時,表單擁有的字段會按照method中的指定方式提交給服務器,而表單提交的字段規則是
表單元素 | type |
規則 |
---|---|---|
<input> |
button |
永遠不提交 |
<input> | checkbox | 只在勾選后提交 |
<input> | file | 永遠提交,即使為空值 |
<input> | hidden | 永遠提交,即使為空值 |
<input> | image | 永遠提交,即使為空值 |
<input> | password | 永遠提交,即使為空值 |
<input> | radio | 只在勾選后提交,如果一組Radio沒有任何勾選,全部不提交。 |
<input> | reset | 永遠不提交 |
<input> | submit | 點擊哪個按鈕,則提交這個按鈕的值,其他的SUBMIT按鈕值都不提交。 如果表單的提交行為是由JavaScript腳本觸發的,則不提交任何值。 |
<input> | text | 永遠提交,即使為空值 |
<button> |
button |
永遠不提交 |
<button> | reset | 永遠不提交 |
<button> | submit | 點擊哪個按鈕提交表單,則提交這個按鈕的值。 如果省略TYPE,IE默認為BUTTON,火狐默認SUBMIT。 |
<select> |
- |
永遠提交,即使為空值。 |
<textarea> |
- | 永遠提交,即使為空值。 |
表格中沒有提到的規則還有:
- 具有disabled屬性的字段不會被提交
- 不具有name屬性的字段不會被提交
- 同名的name屬性會發生覆蓋,radio和checkbox除外
- form指向其他表單的字段,不會被本表單提交
規則來源 http://www.cnblogs.com/manors/archive/2010/03/11/1683727.html
表單序列化
GET方法提交表單,表單字段會被encodeURIComponent轉換,並在url中顯示出來。而post方法提交表單,會在請求body中發送表單字段鍵值對。
在通過JavaScript異步提交表單時,如何按照上面的規則去獲取表單數據,jquery提供了 serialize()
和 serializeArray()
兩個方法。使用該方法會取得和原生表單一致的提交字段。
表單提交事件
表單提交到服務器時,會觸發 submit
事件。也可以通過 form.submit()
手動提交一個表單。
form1.onsubmit = function(event){
event.preventDefault(); // 阻止默認事件,表單將不會提交到服務器
if(confirm('你真的要提交我嗎~')){
this.submit(); // 點擊確定后,表單會被提交
}
}
技巧
不提交空字段
通過上方的表單提交規則可以知道,很多時候,無論是否填寫了值,在提交的時候,該字段都會被提交到服務器。而在執行條件篩選表單提交的時候,由於常用的是GET請求,瀏覽器地址欄中通常會出現一長串字符。
這對於有潔癖的用戶來說是無法忍受的,所以需要在提交表單前做一點小動作,讓值為空的字段不提交到服務器。
// 本段代碼使用了jquery
var form = $('form'),
fields = form.find(':input');
form.on('submit',function(event){
event.preventDefault(); // 阻止默認事件,表單將不會提交到服務器
fields.each(function(){
if(!this.value.length) this.disabled = 'disabled'; // 含有disabled屬性的表單字段將不會被提交
});
this.submit();
})
異步提交文件
一般而言,文件提交都是同步的,因為一般的表單序列化方法,無法傳輸二進制的文件。而如果要實現異步上傳文件的需求,主要依靠兩種方式。
一種是新建一個 iframe
,在里面通過一個獨立的form表單上傳文件后,再和主frame進行通信。另一種則是通過html5的 new FormData()
方法,append進去一個文件,或是直接讀取表單信息。
利用 iframe
方式提交文件的較為知名的插件是 jquery.form.js 。通過 new FormData()
則簡單了許多:
# 這是一個來自 MDN 的示例
// 原生JavaScript方式
var xhr = new XMLHttpRequest();
xhr.open("POST", form1.action);
xhr.send(new FormData(form1));
// 使用jquery的ajax()
$.ajax({
url: form1.action,
type: "POST",
data: new FormData(form1),
processData: false, // 告訴jQuery不要去處理發送的數據
contentType: false // 告訴jQuery不要去設置Content-Type請求頭
});
更多用法請參考 MDN--使用FormData對象 。