沒有關於邊緣案例應該發生什麼的強烈定義,以及需要什麼級別的瀏覽器支持,很難給出一個完美的答案。
有很多,很容易錯過形式的行爲,這就是爲什麼我建議使用維護良好的功能從庫,如jQuery's serializeArray()
:
$('form').serializeArray();
據我瞭解,有一個很大的推動最近要從包括jQuery在內的不必要的事情中解脫出來,所以對於那些對vanilla JS解決方案感興趣的人來說,就是不會這樣做的。
下一個困難來自確定需要什麼級別的瀏覽器支持。 HTMLFormElement.elements
顯着簡化了序列化實現,並且選擇沒有它的形式相關元素是相當痛苦的。
考慮:
<form id="example">...</form>
<input type="text" form="example" name="lorem" value="ipsum"/>
一致性實現需要包括input
元素。我會假設我可以使用,並將其作爲練習留給讀者使用。
之後它不清楚應該如何支持<input type="file"/>
。我並不熱衷於將文件元素不必要地序列化爲一個字符串,所以我已經假定序列化將是輸入的名稱和值,即使該值實際上是無用的。
最後,的輸入結構:
{
'input name': 'value',
'textarea name': 'value'
}
過度幼稚,因爲它不考慮<select multiple>
元件,或者其中兩個輸入端具有相同的名稱的情況。我所做的假設輸入會更好:
[
{
name: 'input name',
value: 'value'
},
{
name: 'textarea name',
value: 'value'
}
]
...並再次離開轉化成不同的結構,它作爲一個練習留給讀者。
給我已經編碼了!
var serialize = (function (slice) {
return function (form) {
//no form, no serialization
if (form == null)
return null;
//get the form elements and convert to an array
return slice.call(form.elements)
.filter(function (element) {
//remove disabled elements
return !element.disabled;
}).filter(function (element) {
//remove unchecked checkboxes and radio buttons
return !/^input$/i.test(element.tagName) || !/^(?:checkbox|radio)$/i.test(element.type) || element.checked;
}).filter(function (element) {
//remove <select multiple> elements with no values selected
return !/^select$/i.test(element.tagName) || element.selectedOptions.length > 0;
}).map(function (element) {
switch (element.tagName.toLowerCase()) {
case 'checkbox':
case 'radio':
return {
name: element.name,
value: element.value === null ? 'on' : element.value
};
case 'select':
if (element.multiple) {
return {
name: element.name,
value: slice.call(element.selectedOptions)
.map(function (option) {
return option.value;
})
};
}
return {
name: element.name,
value: element.value
};
default:
return {
name: element.name,
value: element.value || ''
};
}
});
}
}(Array.prototype.slice));
當你說「even' 應該被支持」時,你期望輸出什麼?你是否期望一個潛在的大文件的全部內容被串行化爲一個字符串?你期待可以用來讀取文件的引用對象嗎?你是否期待字段的實際價值(這只是文件的清理名稱)? – zzzzBov
此外,您的預期輸出無法解釋具有相同名稱的多個表單元素或使用'
你會接受像'method'和'action'屬性添加一些額外的HTML到你的'form'和一個不可見的'iframe'嗎? – antoine129