假设我们有如下 HTML 表单结构:
<form id="target">
<select name="pets" id="pet-select">
<option value="">--Please choose an option--</option>
<option value="dog">Dog</option>
<option value="cat" selected>Cat</option>
<option value="hamster">Hamster</option>
<option value="parrot">Parrot</option>
<option value="spider">Spider</option>
<option value="goldfish">Goldfish</option>
</select>
<select name="friends" multiple>
<option value="D.O" selected>D.O</option>
<option value="O.O">O.O</option>
<option value="K.O" selected>K.O</option>
</select>
<input name="name" value="KAI" />
<input type="password" name="password" value="123456" />
<input type="hidden" name="age" value="66" />
<textarea name="description">I am Superman</textarea>
<input type="checkbox" name="hobby" checked value="sleep" />Sleep
<input type="checkbox" name="hobby" value="eat" />Eat
<input type="radio" name="sex" checked value="Female" />Female
<input type="radio" name="sex" value="Male" />Male
</form>
注意:字段必须具有 name
属性。
我们可以使用以下方法序列化表单数据:
const serializeForm = (formEle) => {
const obj = {}
const formData = new FormData(formEle)
formData.forEach((value, key) => (obj[key] = value))
return obj
}
它已经能获取到大部分值,但是如果您想要支持多选列表或其他具有多个值的表单元素,可以使用如下片段:
const serializeForm = (formEle) =>
Array.from(new FormData(formEle)).reduce(
(p, [k, v]) =>
Object.assign({}, p, {
[k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v
}),
{}
)
思路一样,使用更清晰的写法:
function serializeForm(formEle) {
let obj = {}
let data = new FormData(formEle)
for (let [key, value] of data) {
if (obj[key] !== undefined) {
if (!Array.isArray(obj[key])) {
obj[key] = [obj[key]]
}
obj[key].push(value)
} else {
obj[key] = value
}
}
return obj
}
以下方法序列化由其字段的 name
和 value
组成的表单数据:
const serialize = (formEle) => {
// 获取所有字段
const fields = [].slice.call(formEle.elements, 0)
return fields
.map((ele) => {
const name = ele.name
const type = ele.type
// 忽视:没有 name 的字段、禁用(disabled)字段、文件(file)类型、未选中
checkbox / radio
if (
!name ||
ele.disabled ||
type === 'file' ||
(/(checkbox|radio)/.test(type) && !ele.checked)
) {
return ''
}
// 多选
if (type === 'select-multiple') {
return [...ele.options]
.map((opt) => {
return opt.selected
? `${encodeURIComponent(name)}=${encodeURIComponent(opt.value)}`
: ''
})
.filter((item) => item)
.join('&')
}
return `${encodeURIComponent(name)}=${encodeURIComponent(ele.value)}`
})
.filter((item) => item)
.join('&')
}
查看 How to convert FormData (HTML5 object) to JSON 以了解更多内容。