假设我们有如下 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>

我们可以使用以下方法序列化表单数据:

const serializeForm = formEle => {
  const object = {}
  const formData = new FormData(formEle)
  formData.forEach((value, key) => object[key] = value)
  return object
}

它已经能获取到大部分值,但是如果您想要支持多选列表或其他具有多个值的表单元素,可以使用如下片段:

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
      }),
    {}
  )

console.log(serializeForm(document.querySelector('#target')))

将表单数据序列化为查询字符串

以下方法序列化由其字段的 namevalue 组成的表单数据:

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('&')
}

console.log(serialize(document.querySelector('#target')))

测试效果

更多资料

查看How to convert FormData (HTML5 object) to JSON以了解更多内容。