iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
0
自我挑戰組

不用前端框架 手把手打造基礎SPA網站系列 第 29

[DAY29]番外篇-使用fetch傳送表單資料

昨天我們介紹fetch用get方式來請求資料,並將取得的資料轉為JSON格式做運用,今天要來介紹fetch的post方法,用非同步的方式來傳送表單資料。以下開始進入主題:

準備表單UI

沿用前天彈出表單視窗的範例,為了可以讓程式碼變得更簡短,這裡僅保留表單直接放入render,並去除彈跳視窗功能模組(Modal):

src/pages/Contact.js

//引入外框組件
import { App } from './App'
 
export const Contact = {
    render: () => {
        const content = `
          <div class="container">
            <h1>填寫表單</h1>
            <h6>請填寫下方表單</h6>
              <form>
                <div class="form-group">
                  <label for="name">稱呼</label>
                  <input type="text" class="form-control" name="name" placeholder="請填寫您的稱呼" required>
                </div>
                <div class="form-group">
                  <label for="email">Email</label>
                  <input type="email" class="form-control" name="email" placeholder="請填寫email" required>
                </div>
                <div class="form-group">
                  <label for="message">留言內容</label>
                  <textarea type="email" class="form-control" name="message" placeholder="請填寫內容" required></textarea>
                </div>
                <div class="form-group">
                  <button type="submit" class="btn btn-primary" id="submit">提交</button>
                </div>
              </form>
          </div>
        `
 
        return App.render(content)
    },
}

表單裡我們放置三個輸入框,依序是name、email及message,為了等等傳送表單資料(formData),將每個輸入框給予name屬性,最後再放置一個送出的submit button。

fetch傳送表單

我們先看看下面的例子,這是所熟知最傳統的方式,使用html的form來傳送,要傳送表單資料除了設定method為POST,enctype也要設定為multipart/form-data。

<form action="https://test.com/post" method="POST" enctype="multipart/form-data">

不過這樣的方式會造成請求資源的同時做轉址,轉向至action設定的 「https://test.com/post」 ,為了不讓瀏覽器產生轉址,我們可以使用javascript建立表單物件,搭配使用非同步的方式來傳送資料。直接來看fetch POST如何運行:

src/pages/Contact.js

export const Contact = {
    listener: {
        click: function (e) {
            if (
                e.target.closest('button') &&
                e.target.closest('button').id === 'submit'
            ) {
                //取消預設submit事件
                e.preventDefault()
 
                // 建立formData物件
                const fd = new FormData(document.querySelector('form'))
 
                // fetch post
                fetch('test.com/post', {
                    method: 'POST',
                    body: fd,
                    headers: { 'Content-Type': 'multipart/form-data' },
                })
                .then((res) => res.json())
                .then((data) => {
                    console.log(data)
                })
            }
        },
    },
    render: () => {

這邊新增listener屬性來增加click監聽事件,需要注意的是當按下submit按鈕時,要用preventDefault()取消預設submit事件,否則會轉址。建立表單物件起手式,宣告並建立FormData表單物件,可以帶入現有的表單做傳送,或是建立後使用append來增加表單資料,參閱MDN上面的說明:

FormData 介面可為表單資料中的欄位/值建立相對應的的鍵/值對(key/value)集合,之後便可使用 XMLHttpRequest.send() 方法來送出資料。它在編碼類型設定為 multipart/form-data 時會採用與表單相同的格式送出。

在fetch的第一個參數放入URI,因為手邊沒有API,所以先隨意打,這邊只要了解body夾帶的資料內容。比較重要的是第二個參數設定如下:

{
    method: 'POST',
    body: fd,
    headers: { 'Content-Type': 'multipart/form-data' },
}
  • method:表示設置傳輸方式為POST
  • body:要傳輸的訊息,這裡放置我們剛剛建立的表單物件,若傳輸JSON格式資料記得用JSON.stringify轉為字串
  • headers:HTTP傳輸的內容類型, multipart/form-data表示傳送表單物件,若傳輸JSON格式資料可以改為application/json

測試結果

填完資料後按下送出,用Chrome Devtools到Network看看body傳送的資訊:

可以看到框框處是formData裡面傳送的資料,其中key對應form表單的name,value對應為填入表單的值。以上就是使用fetch post來傳輸資料,以上實做到這裡算是結束了,準備迎接完賽日的到來吧:)


上一篇
[DAY28]番外篇-使用fetch發送請求
下一篇
[DAY30]完賽篇-期待成為更好的自己
系列文
不用前端框架 手把手打造基礎SPA網站30

尚未有邦友留言

立即登入留言