序列化表单数据

假设我们有如下 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以了解更多内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值