Form 表單提交知識的總結(全)

不做祖國的韭菜發表於2018-10-17

原文連結: www.jianshu.com/p/b7cd1ae17…

前言: html 中的form元素被稱之為表單,form元素中的內容,包含有互動控制元件,其目的是用來向web 伺服器提交資訊,實現前後端的互動目的。相關基礎內容參照form基礎知識文件 ,文章將會啟動一個node 後臺伺服器,對前端form 表單的各種場景以及後端對請求結果的響應做一個歸納總結

1. node服務提供請求地址

   我們通過express 來啟動後臺服務,並且模擬兩個後臺介面

const express = require('express')
const app = express()
const bodyParser = require('body-parser')

// 處理請求 的content-type 為application/json
app.use(bodyParser.json())

//處理請求的content-type 為application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
  extended: false
}))
app.get('/user', (req, res) => {
  console.log(req.query)
  res.send('成功接收')
})


app.post('/user', (req, res) => {
  console.log(req.body)
  res.send('成功接收')
})
app.listen(3008, () => {
  console.log('服務啟動')
})
複製程式碼

2. 普通的form 表單提交

  form 表單通過method 的屬性來確定提交給後臺的請求方式,兩者的基本用法如下

<!-- form 表單post提交,預設會重新整理到 action 頁面 -->
    <form action="http://localhost:3008/user" method="POST" name="post提交">
      <p>name: <input type="text" name="username"></p>
      <p>password: <input type="password" name="password"></p>
      <input type="submit" value="提交">
    </form>
    
<!-- form 表單get 提交, 預設重新整理action 頁面 -->
    <form action="http://localhost:3008/user" method="GET" name="get提交">
      <p>name: <input type="text" name="username"></p>
      <p>password: <input type="password" name="password"></p>
      <input type="submit" value="提交">
    </form>
複製程式碼

以下幾點需要特別注意

  1. form 的提交行為需要通過type=submit實現
  2. form 中的method 屬性不指定時, form 預設的提交方式為 get請求。
  3. form 表單的提交後會有預設行為,會跳轉重新整理到action 的頁面
  4. form 表單的提交方式,==請求頭預設的content-type 為 x-www-form-urlencoded==
  5. 當一個form 表單內部,所有的input 中只有一個 type='text' 的時候,enter 鍵會有預設的提交行為(注意前提條件)。

3. 阻止新頁面跳轉

從前面可以知道,form 表單的提交會伴隨著跳轉到action中指定 的url 連結,為了阻止這一行為,可以通過設定一個隱藏的iframe 頁面,並將form 的target 屬性指向這個iframe,當前頁面iframe則不會重新整理頁面

<!-- 無重新整理頁面提交 -->
    <form action="http://localhost:3008/user" method="POST" name="post提交" target="targetIfr">
      <p>name: <input type="text" name="username"></p>
      <p>password: <input type="password" name="password"></p>
      <input type="submit" value="提交">
    </form>
    <iframe name="targetIfr" style="display:none"></iframe>
複製程式碼

4. 指令碼觸發form 表單的提交行為

js事件觸發表單提交,通過button、連結等觸發事件,js呼叫submit()方法提交表單資料,jquery通過submit()方法

<!-- html -->
<!-- 通過js 進行表單的提交 存在問題,頁面會跳轉重新整理-->
    <form action="http://localhost:3008/user" method="POST" name="jsForm" target="targetIfr" id="jsForm">
      <p>name: <input type="text" name="username"></p>
      <p>password: <input type="password" name="password"></p>
      <button id="btn">提交</button>
    </form>

    <!-- 通過jquery 進行表單的提交 存在問題,並阻止頁面跳轉重新整理-->
    <form action="http://localhost:3008/user" method="POST" name="jqueryForm" target="targetIfr" id="jqueryForm">
      <p>name: <input type="text" name="username"></p>
      <p>password: <input type="password" name="password"></p>
      <button id="jqbtn">提交</button>
    </form>
複製程式碼
// js
var btn = document.getElementById('btn')
var jsForm = document.getElementById('jsForm')
btn.onclick = function () {
    jsForm.submit()
}
// jquery
$('#jqbtn').click(function () {
  $('#jqueryForm').submit(function () {
    console.log('submit success')
    return false
  })
})
複製程式碼

說明:

  1. 通過指令碼提交行為依然存在跳轉 新頁面重新整理的問題
  2. 指令碼中可以通過阻止預設行為來禁止頁面跳轉

5. ajax 提交請求

<!-- ajax 請求 -->
    <form method="POST">
      <p>name: <input type="text" name="username"></p>
      <p>password: <input type="password" name="password"></p>
      <div id="jqbtn">提交</div>
    </form>
複製程式碼
 $('#jqbtn').click(function () {
      $.ajax({
        url: 'http://localhost:3008/user',
        type: 'POST',
        data: JSON.stringify(params),
        contentType: "application/json", // 預設以formdata形式傳送給後臺
        dataType: "json",
        success: function (res) {
          console.log(res)
        }
      })
    })
複製程式碼

注意事項:

  1. 通過ajax 請求模擬form 的提交需要注意 form 表單內 不允許 <button type="submit"></button>的存在,否則會和ajax 自身的請求相沖突
  2. ajax 請求中,預設的content-type 為'formdata',可根據自己的需要修改
  3. 後臺對不同的content-type 請求頭的處理如下
// 處理請求 的content-type 為application/json
app.use(bodyParser.json())

//處理請求的content-type 為application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
  extended: false
}))
複製程式碼
  1. ajax 請求需要處理跨域問題,而form 表單的預設提交不需要,原因是,==原頁面用form 提交到另一個域名之後,原指令碼無法獲取響應的內容,所以瀏覽器認為這是安全的,而ajax 需要處理響應的內容,瀏覽器則認為這是一種跨域的行為==
  2. 為了解決ajax 的跨域問題,需要在後臺的程式碼中加入跨域的處理
const cors = require("cors")
// 解決跨域
app.use(cors())
複製程式碼

6. FormData 處理檔案的上傳

檔案的上傳,請求頭中content-type 的形式需要修改為multipart/form-data, 相應的,只要將form的enctype 屬性修改為enctype="multipart/form-data"即可

<!-- FormData -->
    <form action="http://localhost:3008/user" method="POST" enctype="multipart/form-data">
      <p><input type="file" name="file"></p>
      <input type="submit" value="提交">
    </form>
複製程式碼

後臺處理部分,我們需要額外安裝formidable 依賴來解決form-data 格式的解析

const formidable = require('formidable')

const form = new formidable.IncomingForm();

app.post('/user', (req, res) => {
  form.parse(req, function (err, fields, files) {
    console.log(files)
    res.send('成功接收')

  })
})
複製程式碼

7.總結

form 表單前後端的處理彙總如上,詳細的程式碼可以參考 github

相關文章