先看一個簡單的例子
比如這裏有一個簡單的 form 表單
<form id="form">
<input name="user" type="text">
<div>
<input type="radio" name="A" value="r1">r1
<input type="radio" name="A" value="r2">r2
<input type="radio" name="A" value="r3">r3
<input type="radio" name="A" value="r4">r4
</div>
<div>
<input type="checkbox" name="B" value="c1">c1
<input type="checkbox" name="B" value="c2">c2
<input type="checkbox" name="B" value="c3">c3
<input type="checkbox" name="B" value="c4">c4
</div>
<button type="submit">login</button>
<button type="reset">reset</button>
</form>
頁面如下
現在,隨便輸入點內容
如果提交,表單會觸發默認行為,直接以get方式提交到當前頁
可以看到這些參數正是我們輸入的參數。
表單的默認行為
通常我們都會把這些默認行為阻止掉,畢竟都不希望在提交表單會跳轉到另一個頁面,或者刷新整個頁面
form.addEventListener("submit", (ev) => {
ev.preventDefault();
// 自己發請求
})
那麼,我需要如何拿到這些提交的值呢?
表單提交的數據類型
根據數據類型來劃分,通常使用的表單提交數據格式大概有以下幾種
- formdata格式,需要通過 new FormData 創建
- json格式,形如
{ a:1,b:2,c=3 } - url字符串拼接,形如
a=1&b=2&c=3
1.formdata
通常 formdata 的使用方式如下
var formData = new FormData();
formData.append('username', 'xboxyan');
formData.append('password', '123456');
但是對於 form 來説,大可以不必採用這樣的方式,直接通過以下方式獲取
var formData = new FormData(form); // form為表單對象
所以,針對表單容器就不要再用 div 了!
為了更加方便的使用,這裏簡單擴展一下 form 屬性
/* formdata */
Object.defineProperty(HTMLFormElement.prototype, 'formdata', {
get() {
return new FormData(this);
}
})
這樣就可以通過form.formdata來獲取了
FormData對象的值是不可見的,需要通過get方式才能看到
關於 FormData 的更多操作可參考 https://developer.mozilla.org...
2.jsondata
json 格式也是非常常用的一種數據傳遞方式了,不過原生 form 並沒有直接獲取的方式,只能自己封裝了。
這裏可以直接在上面 FormData 的基礎上遍歷一次即可,由於有些值會有多個,比如上面的多選框,這裏直接轉成了數組,具體實現如下
/* jsondata */
Object.defineProperty(HTMLFormElement.prototype, 'jsondata', {
get() {
const jsondata = {}
const formdata = new FormData(this);
formdata.forEach((value, key) => {
if (!jsondata[key]) {
jsondata[key] = formdata.getAll(key).length > 1 ? formdata.getAll(key) : formdata.get(key);
}
});
return jsondata;
}
})
這樣就可以通過form.jsondata來獲取了
3.urldata
還有一種方式在get請求中會用到,就是 url拼接方式,這個原生也沒有直接的方案,可以藉助上面jsondata轉換一下,這裏做了一個小改動,比如默認的多選是b=1&b=2&b=3&c=1,這裏改造成了b=1,2,3&c=1,具體實現如下
/* urldata */
Object.defineProperty(HTMLFormElement.prototype, 'urldata', {
get() {
const urldata = [];
Object.entries(this.jsondata).forEach(([key, value]) => {
urldata.push(key + '=' + (value.join ? value.join() : value))
})
return urldata.join('&');
}
})
這樣就可以通過form.urldata來獲取了
總結
通過以上3個方法,基本可以滿足日常開發的絕大部分需求,前提是 html 足夠規範,表單就必須是 form,單選就必須是 input radio等等,很多前端同學或者説很多框架都喜歡用 div 來模擬,以至於這些原生特性就直接被拋棄掉了,豈不可惜?
最後,附上以上全部源碼
/* jsondata */
Object.defineProperty(HTMLFormElement.prototype, 'jsondata', {
get() {
const jsondata = {}
const formdata = new FormData(this);
formdata.forEach((value, key) => {
if (!jsondata[key]) {
jsondata[key] = formdata.getAll(key).length > 1 ? formdata.getAll(key) : formdata.get(key);
}
});
return jsondata;
}
})
/* formdata */
Object.defineProperty(HTMLFormElement.prototype, 'formdata', {
get() {
return new FormData(this);
}
})
/* urldata */
Object.defineProperty(HTMLFormElement.prototype, 'urldata', {
get() {
const urldata = [];
Object.entries(this.jsondata).forEach(([key, value]) => {
urldata.push(key + '=' + (value.join ? value.join() : value))
})
return urldata.join('&');
}
})