51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Form前端开发:继续深入form 标签与FormData 的应用

500.jpg

上篇文章,我们分享了"前端开发:一起了解下HTML表单(form)中form-data的玩法"。今天继续以 <form> 这个标签为主题,探讨浏览器如何处理这个HTML 标签,以及身为开发者的我们应该注意哪些事情。

具体来说,这篇文章会包含下列几个有关于表单应用的部分:

  • <form/>标签背后做了哪些事

  • FormData 在JavaScript 当中的应用

  • FormData 与 fetch 的搭配

  • JavaScript 如何操作档案上传

再谈form 标签 {#再談-form-標籤}

HTML 的form 标签里头其实有许多浏览器帮你实作的细节,开发者有时候会忽略。以下面的例子来说:

<form method="POST" action="/upload" enctype="multipart/form-data">
  <input type="text" name="name" />
  <input type="file"  name="file" />
  <button>
    Submit
  </button>
</form>

在没有任何JavaScript 程式码的情况下,按下Submit 按钮之后浏览器会帮你做这些事情:

  • 序列化input 当中的name 与file 栏位

  • 以POST 方法送出 Content-Type: multipart/form-data 的HTTP 请求

  • 读取档案并加入到请求内容中(如果档案存在)

在单页应用、前端框架还不流行的时候,用form 表单填写资料送出,然后重新导向到其他页面是常见的做法。但是当填写的资料变多,或是只有部分区域需要更新(例如留言等)时每次都要整页更新对使用者来说体验并不好,所以逐渐衍生出透过ajax 打API,并用JavaScript 动态更新资料的做法。

ojS9WT7wufNVq34dr5Kt7N.jpg

虽然动态更新的方式的确改善了使用者体验,但是要实现一个好的表单设计却需要考虑许多细节:

  • 错误处理

  • 状态转换

  • 资料保存

  • Accessibility

很多时候只要一个环节没有做好,使用者反而还宁愿用单纯整页更新的表单标签来操作。对于像是后台应用来说,用 <form> 表单来做整页更新往往可以省下很多开发时间,甚至依赖浏览器的内建机制运作起来更加稳定。

FormData 在JavaScript 中的应用 {#formdata-在-javascript-中的應用}

FormData定义了一个介面方便开发者做像是key/value 的应用,最常见的就是表单处理。一个 FormData 的宣告可以这样子写:


const formData = new FormData()
//                key     value
formData.append('name', 'Kalan');

如果将form 的element 放到 FormData 当中,会自动将里头填写的资讯直接序列化成FormData

<form id="form" enctype="multipart/form-data" action="/upload" method="POST">
  <input type="text" name="name" />
  <input type="file" name="file" />
  <button>Submit</button>
</form>
<script>
  const formData = new FormData(document.getElementById('form'));
  formData.get('name'); // 取得目前 input 的值
  formData.get('file'); // 取得目前的檔案
</script>

打开console,发现如下显示:

image.png

除此之外,如果将FormData 放到fetch 的body 里头,浏览器会自动帮你以 multipart/form-data 的形式传送:

const formData = new FormData();
formData.append('name', 'Kalan');
formData.append('file', new File(['Hello World'], 'file.txt', { type: 'text/plain' }))
fetch('/upload', {
  method: 'POST',
  body: formData
})

在执行完上面的JavaScript 程式码并观察Network 的请求,可以发现尽管没有特别定义Content-Type,浏览器还是会帮我们以 multipart/form-data 的方式传送,form data 的序列化也是由浏览器完成image.png

总结 {#總結}

这两篇文章解释了 multipart/form-data 的应用与实际使用方法。第一篇文章解释了 Content-Disposition 的含义, boundary 的用途,以及multipart/form-data 的请求如何构造;第二篇文章说明了在实务上我们可以怎么使用form 与FormData,并透过JavaScript 来做FormData 的处理与档案上传。

对于伺服器端来说,在网页上做档案上传的动作也是一个HTTP 请求,所以伺服器端必须要根据Header 当中的资讯以及 multipart/form-data 定义的格式来解析资料,才有办法正确拿到档案内容,通常这些解析都已经被框架处理掉,但是在这边要特别注明的是,在网页上传递档案没有太神奇的魔法,背后仍然是奠基在HTTP 请求之上。


赞(0)
未经允许不得转载:工具盒子 » Form前端开发:继续深入form 标签与FormData 的应用