Skip to content

Latest commit

 

History

History
126 lines (107 loc) · 3.39 KB

序列化表单数据.md

File metadata and controls

126 lines (107 loc) · 3.39 KB

序列化表单数据

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

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

以下方法序列化由其字段的 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('&')
}

测试效果

更多资料

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