|
一個 form post 也可以繞個一大圈 |
網頁傳統 form 要傳遞參數值時,會使用 action,寫法大致如下:
<form action="http://localhost:8080/login" method="post">
<h1>Form Action Test</h1>
<input type="text" name="email" value="Eden" />
<input type="password" name="password" value="L@veEden" />
<input type="submit" value="Submit">
</form>
可以看到 submit 時,Request 的 Content-Type 屬性是很標準的 application/x-www-form-urlencoded。
這個方式很標準,絕大部份的 Web Server 都可以接受,當然也包含了 Delphi Web Server。
時代在進步,JavaScript 標準都來到 2020,所以當然要試一下新的操作方法。
JavaScript 裡有 FormData 類別,可以建構 form 物件,寫法如下:
<form id="login-form" onsubmit="handleSubmit(event)">
<input type="text" name="email" value="Eden" />
<input type="password" name="password" value="L@veEden" />
<input type="submit" value="Submit">
</form>
<script>
function handleSubmit(event) {
event.preventDefault()
let formData = new FormData(document.getElementById('login-form'))
fetch("http://localhost:8080/login", {
method: "POST",
body: formData
})
}
</script>
實際 submit 時 Request 的 Content-Type 屬性是 multipart/form-data,如下圖所示:
multipart/form-data 相對於 application/x-www-form-urlencoded 比較少見,故某些 Web Server 預設是不會處理 multipart/form-data 的格式內容。
既然後端需要做調整,如果前端事先做好,那後端不就更省事?
前端調整
仿照傳統規則
前端仿照傳統的作法實作,程式碼如下:
<form id="login-form" onsubmit="handleSubmit(event)">
<input type="text" name="email" value="Eden" />
<input type="password" name="password" value="L@veEden" />
<input type="submit" value="Submit">
</form>
<script>
function handleSubmit(event) {
event.preventDefault()
let formElement = document.getElementById("login-form")
let formData = ""
formData = "email=" + formElement[0].value
formData = formData + "&password=" + formElement[1].value
fetch("http://localhost:8080/login", {
method: "POST",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: formData
})
}
</script>
執行結果
修改後就能讓 Web Server 順利解析參數。
使用 URLSearchParams
URLSearchParams 是個處理各種URL查詢參數轉換的類別,在這個例子只需要將 FormData 再丟入 URLSearchParams 處理過,即能得到 application/x-www-form-urlencoded 所需的查詢參數,程式如下所示:
<html>
<head></head>
<body>
<form id="login-form" onsubmit="handleSubmit(event)">
<input type="text" name="email" value="Eden" />
<input type="password" name="password" value="L@veEden" />
<input type="submit" value="Submit">
</form>
<script>
function handleSubmit(event) {
event.preventDefault()
let formData = new FormData(document.getElementById('login-form'))
var searchParams = new URLSearchParams(formData);
fetch("http://localhost:8080/login", {
method: "POST",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: searchParams
})
}
</script>
</body>
</html>
執行結果
一樣修改後就能讓 Web Server 順利解析參數。
總結
新方法但沿用舊觀念,在某些前端框架看不到的細節還是要拆成香草JS小部件來多做嘗試才行。
前端修改下我會偏好使用 URLSearchParams,在開發上比較省力,程式也比較好懂。
以上提供各位參考。謝謝大家收看!
【2021.05.18 更新】
jQuery 和 form 的結合
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.6.0.js"
integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
crossorigin="anonymous"></script>
</head>
<body>
<form id="login-form" onsubmit="handleSubmit(event)">
<input type="text" name="email" value="Eden" />
<input type="password" name="password" value="L@veEden" />
<input type="submit" value="Submit">
</form>
<script>
function handleSubmit(event) {
event.preventDefault()
const formData = {user:document.getElementByName("user").value, password:document.getElementByName("password").value}
// item 的內容也可以用 $.ajax.beforeSend 替換
const item = {
'url': "http://localhost:8080/login",
'type': 'POST',
'headers': {
'Authorization': `Basic ${ base64Auth }`,
},
//'contentType': false, // Default = application/x-www-form-urlencoded
//'processData': false, // false = jq 不轉譯 Json to Parameters; Default=True
'data': formData
}
$.ajax(item)
.done(function (response) {
console.log(response)
})
.fail(function (response) {
console.log('Fail : ' + response.responseText)
})
}
</script>
</body>
</html>