Koa 提交和接收 JSON 表單數據


來自 url 中的 query 參數可直接通過 context.query 獲取,但 POST 方式提交的表單數據則需要借助中間件的解析來完成,比如 koa-bodyparser

首先准備好一個表單頁面,為了演示,其中包含一個數組類型的數據。

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>post json</title>
  </head>
  <body>
    <form action="/save" method="POST">
      <div>
        <label for="name"
          >name:
          <input type="text" name="name" id="name" value="Tom" />
        </label>
      </div>
      <div>
        <label for="age"
          >age:
          <input type="number" name="age" id="age" value="19" />
        </label>
      </div>
      <div>
        <label
          >hobbies:
          <br />
          <input
            type="text"
            name="hobbies[0]"
            id="hobbies[0]"
            value="reading"
          />
          <br />
          <input type="text" name="hobbies[1]" id="hobbies[1]" value="music" />
          <br />
          <input type="text" name="hobbies[2]" id="hobbies[2]" value="swim" />
        </label>
      </div>
      <button type="submit">Submit</button>
    </form>
  </body>
</html>

server.js

var Koa = require("koa");
var Router = require("koa-router");
var fs = require("fs");
var bodyParser = require("koa-bodyparser");

var app = new Koa();
var router = new Router();

app.use(bodyParser());

router.get("/", async (ctx, next) => {
ctx.type = "html";
ctx.body = fs.createReadStream("index.html");
});

router.post("/save", async (ctx, next) => {
ctx.body = ctx.request.body;
});

app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);

console.log("server started at http:localhost:3000");

通過 Node.js 調試模式啟動服務可查看到接收到的數據,其中數據類型解析正常。

$ node --inspect-brk server.js
server started

接收到的表單數據

接收到的表單數據

但其實前台頁面提交的並不是 JSON 類型,這是 koa-bodyparse 解析后的結果。通過 Chrome Devtools 的網絡面板可看到,真實的類型為 Request 中 Content-Type 字段,為 application/x-www-form-urlencoded

表單提交時的請求類型為 application/x-www-form-urlencoded

表單提交時的請求類型為 `application/x-www-form-urlencoded`

原生的 HTML 表單 <form> 是沒有 JSON 類型的,其總共有三種默認的格式,

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

默認為 application/x-www-form-urlencoded,可通過 <form> 表單的 enctype 指定。

所以真正意義上以 JSON 格式提交,需要借助 JavaScript,真實場景下表單也大多會走代碼提交而非原生 submit 類型的 <button>

首頁更新表單代碼添加 onsubmit 方法:

- <form action="/save" method="POST">
+ <form action="/save" method="POST" onsubmit="submitForm(event)" id="myForm">

添加以下代碼到頁面以提交表單:

<script>
    function submitForm(event) {
        event.preventDefault();
        var formData = new FormData(myForm);
        let data = {};
        for (var [key, value] of formData.entries()) {
            if (key.startsWith("hobbies")) {
            data["hobbies"]
                ? data["hobbies"].push(value)
                : (data["hobbies"] = [value]);
            } else {
            data[key] = value;
            }
        }
    <span class="pl-en">fetch</span>(<span class="pl-s"><span class="pl-pds">"</span>/save<span class="pl-pds">"</span></span>, {
        method<span class="pl-k">:</span> <span class="pl-s"><span class="pl-pds">"</span>POST<span class="pl-pds">"</span></span>,
        headers<span class="pl-k">:</span> {
        <span class="pl-s"><span class="pl-pds">"</span>Content-Type<span class="pl-pds">"</span></span><span class="pl-k">:</span> <span class="pl-s"><span class="pl-pds">"</span>application/json<span class="pl-pds">"</span></span>
        },
        body<span class="pl-k">:</span> <span class="pl-c1">JSON</span>.<span class="pl-c1">stringify</span>(data)
    })
        .<span class="pl-c1">then</span>(<span class="pl-k">function</span>(<span class="pl-smi">response</span>) {
        <span class="pl-k">return</span> <span class="pl-smi">response</span>.<span class="pl-en">json</span>();
        })
        .<span class="pl-c1">then</span>(<span class="pl-k">function</span>(<span class="pl-smi">response</span>) {
        <span class="pl-en">console</span>.<span class="pl-c1">log</span>(response);
        });
}

</script>

最后完整的后台與頁面代碼為:

server.js
var Koa = require("koa");
var Router = require("koa-router");
var fs = require("fs");
var bodyParser = require("koa-bodyparser");

var app = new Koa();
var router = new Router();

app.use(bodyParser());

router.get("/", async (ctx, next) => {
ctx.type = "html";
ctx.body = fs.createReadStream("index.html");
});

router.post("/save", async (ctx, next) => {
ctx.body = ctx.request.body;
});

app.use(router.routes()).use(router.allowedMethods());
app.listen(3000);

console.log("server started at http:localhost:3000");

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>post json</title>
  </head>
  <body>
    <form action="/save" method="POST" onsubmit="submitForm(event)" id="myForm">
      <div>
        <label for="name"
          >name:
          <input type="text" name="name" id="name" value="Tom" />
        </label>
      </div>
      <div>
        <label for="age"
          >age:
          <input type="number" name="age" id="age" value="19" />
        </label>
      </div>
      <div>
        <label
          >hobbies:
          <br />
          <input
            type="text"
            name="hobbies[0]"
            id="hobbies[0]"
            value="reading"
          />
          <br />
          <input type="text" name="hobbies[1]" id="hobbies[1]" value="music" />
          <br />
          <input type="text" name="hobbies[2]" id="hobbies[2]" value="swim" />
        </label>
      </div>
      <button type="submit">Submit</button>
    </form>
    <script>
      function submitForm(event) {
        event.preventDefault();
        var formData = new FormData(myForm);
        let data = {};
        for (var [key, value] of formData.entries()) {
          if (key.startsWith("hobbies")) {
            data["hobbies"]
              ? data["hobbies"].push(value)
              : (data["hobbies"] = [value]);
          } else {
            data[key] = value;
          }
        }

        fetch("/save", {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify(data)
        })
          .then(function(response) {
            return response.json();
          })
          .then(function(response) {
            console.log(response);
          });
      }
    </script>
  </body>
</html>

再次查看提交時的 Content-Type 及所提交的數據,已經是 JSON 格式了。

通過 fetch 提交 JSON 格式的表單數據

通過 fetch 提交 JSON 格式的表單數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM