Ajax 之 FormData 格式数据

发布于 2023-05-10 15:35:50 字数 3527 浏览 62 评论 0

表单编码

当用户提交表单时,表单中的数据(每个表单元素的名字和值)编码到一个字符串并随请求发送。默认情况下,HTML 表单通过 POST 方法发送给服务器,而编码后的表单数据则用做请求主体。

对表单数据使用的编码方案相对简单:对每个表单元素的名字和值执行普通的 URL 编码(使用十六进制转义码替换特殊字符),使用 = 把编码后的名字和值分开,并使用 & 符号分开 名/值对

一个简单的表单的编码如下所示:

name=Frankie&age=20&height=180

表单数据编码格式有一个正式的 MIME 类型:

application/x-www-form-urlencoded

当使用 POST 方法提交这种顺序的表单数据市,必须将请求头 Content-Type 设置为该值。
注意:这种类型的编码并不需要 HTML 表单,在 Ajax 应用中,希望发送给服务器的很可能是一个 JavaScript 对象,前面展示的数据变成 JavaScript 对象的表单编码形式可能是:

{ name: 'Frankie', age: 20, height: 180 }

表单编码在 Web 上如此广泛地使用,同时所有服务器端的编程语言都能得到良好的支持,所以非表单数据的表单编码通常也是容易实现的事情,下面代码展示如何实现对象属性的表单编码:

function encodeFormData(data) {
  if (!data) return ''
  const pairs = []    // 用于保存名值对
  for (let key in data) {
    if (!data.hasOwnProperty(key) || typeof data[key] === 'function') {
      continue
    }
    let value = data[key].toString()                        // 把值转换成字符串
    let name = encodeURIComponent(key.replace('%20', '+'))  // 编码名字
    value = encodeURIComponent(value.replace('%20', '+'))   // 编码值
    pairs.push(name + '=' + value)
  }
  return pairs.join('&')  // 返回使用'&'连接的名值对
}

const data = { name: '越前君', age: 20, height: 180 }
console.log(encodeFormData(data))   // name=%E8%B6%8A%E5%89%8D%E5%90%9B&age=20&height=180

表单序列化

随着 Ajax 的出现,表单序列化已经成为一种常见的需求,在 JavaScript 中,可以利用表单字段的 type 属性,连同 namevalue 属性一起实现对表单序列化。在编写代码之前,有必要先弄清楚在表单提交期间,浏览器是如何将数据发送给服务器的。

  • 对表单字段的名称和值进行 URL 编码,使用 & 分隔;
  • 不发送禁用的表单字段;
  • 只发送勾选的复选框和单选框按钮;
  • 不发送 typeresetbutton 的按钮;
  • 对选选择框中,每个选中的值单独一个条目;
  • 在单击提交按钮提交表单的情况下,也会发送提交按钮;否则,不发送提价按钮。也包括 typeimage<input> 元素;
  • <select> 元素的值,就是选中的 <option> 元素的 value 属性值。 如果 <option> 元素没有 value 属性,则是 <option> 元素的文本值

在表单序列化过程中,一般不包括任何按钮字段,因为结果字符串很可能是通过其他方式提交的。除此之外的其他上述规则都应该遵循。

在下面表单序列化 serialize() 函数中,首先定义了一个名为 parts 数组,用于保存将要创建的字符串的各个部分。然后,通过 for 循环遍历每个表单字段,并将其保存在 field 变量中。在活动一个字段的引用之后,使用 switch 语句检测其 type 属性。

序列化过程中最麻烦的就是 <select> 元素,它可能是单选框,也可能是多选框。为此,需要遍历控件中的每一个选项,并在相应选项被选中的情况下向数组添加一个值。对于单选框,只有一个选中项,而多选框则可能有零个或多个选中项。这里的代码适用于这两种选择框,至于可选项的数量则是由浏览器控制的。在找到一个选中项之后,需要确定使用什么值。如果不存在 value 属性,或者虽然存在该属性,但值为空字符串,都要使用选项的文本来代替。为检查这个特性,在 DOM 兼容的浏览器中需要使用 hasAttribute() 方法,而在 IE7 中需要使用属性 specified 属性。

如果表单中包含 <fieldset> 元素,则该元素会出现在元素集合中,但没有 type 属性。因此,如果 type 属性未定义,则不需要对其进行序列化。同样,对于各种按钮以及文件输入字段也是如此(文件输入字段在表单提交过程中包含文件的内容;但是,这个字段是无法模仿的,序列化时一般都要忽略)

对于单选按钮和复选框,要检查其 checked 属性是否被设置为 false,如果是则退出 switch 语句。如果 checked 属性是 true,则继续执行 default 语句,即将当前字段的名称和值进行编码,然后添加到 parts 数组中。函数的最后一步,就是使用 join() 个数整个字符串,也就是用 & 来分隔每一个表单字段。

最后 serialize() 函数会以查询字符串的格式输出序列化之后的字符串。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

夏末染殇

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

eins

文章 0 评论 0

世界等同你

文章 0 评论 0

毒初莱肆砂笔

文章 0 评论 0

初雪

文章 0 评论 0

miao

文章 0 评论 0

qq_zQQHIW

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文