在前幾天,我們已經學會如何用 Vue 建構出完整的前端互動應用,也成功拆解了組件。但這些功能目前都還停留在「瀏覽器的世界
」。
今天我們要邁出關鍵的一步:學習與外部世界對話的魔法——HTTP Request,也就是大家常說的 Call API。
為什麼要這樣做?
單機運作
,例如計算機、離線計時器,其實可以不必後端。我們會先用一張 HTTP 示意圖,幫助大家理解請求 (Request) 與回應 (Response) 的完整過程,然後分析使用者需求、建立 User Story,再到程式實作,完整體驗前端到後端的資料流。
單純前端執行的情境
你的程式碼不需要永久保存或跨裝置傳輸資料,例如單機的待辦清單、計算機。這種情況可以直接打包成可執行檔或 PWA (Progressive Web App) 使用。
需要後端的情境
若需要:
結論:當系統要「儲存、整合或跨裝置交換資料」時,API 就是必修的魔法。
以下示意圖可以幫助理解:
更多HTTP API的介紹可以參考我去年python說明:
👉 我之前的後端教學文章python版
以我們的 飲料點單系統為例:
GET /api/orders
POST /api/orders
以下用 時序圖 來描述一個新增訂單的流程:
onMounted
可用來在畫面初始化時發送 GET 請求ref
、reactive
管理 loading
與 error
狀態submit
事件今天我們會簡單介紹前後端怎麼建立跟互相溝通
再把後端data(order.json)傳回前端
前端在把資料(訂單)送到後端
我們先建立在一個folder叫做basic server(用來存後端的程式碼跟資料檔)
order.json
[
{ "id": "1", "name": "Alice", "drink": "紅茶" },
{ "id": "2", "name": "Bob", "drink": "綠茶" }
]
這個當作我們的初始化data
server.js
在開始之前我們需要先下指令安裝套件
初始化package.json
npm init -y
express是簡單的後端框架,cors是跨網域使用的套件
ps 就算是在同樣主機上開發,不同port也會被瀏覽器認定不同domain
npm install express cors
import express from "express";
import { promises as fs } from "fs";
import path from "path";
import { fileURLToPath } from "url";
import cors from "cors"; // 👈 新增
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = 3000;
const DATA_FILE = path.join(__dirname, "order.json");
// ✅ 啟用 CORS(允許所有來源)
app.use(cors());
app.use(express.json());
// 取得所有訂單
app.get("/api/orders", async (_req, res) => {
const txt = await fs.readFile(DATA_FILE, "utf8");
res.json(JSON.parse(txt));
});
// 新增一筆訂單
app.post("/api/orders", async (req, res) => {
const orders = JSON.parse(await fs.readFile(DATA_FILE, "utf8"));
const order = {
...req.body,
id: Date.now().toString(),
createdAt: new Date().toISOString(),
};
orders.push(order);
await fs.writeFile(DATA_FILE, JSON.stringify(orders, null, 2), "utf8");
res.status(201).json(order);
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
node server.js
接者我們就可以在網址上看到訂單有沒有出來(get methods可以沒有限定的情況下可以直接瀏覽response)
http://localhost:3000/api/orders
接下來我們可以用指令來創建一個新的前端folder來玩玩看
npm create vite@latest basic -- --template vue
今天設計得檔案結構大概會是這樣
my-vue-app/
├─ server.js # 你的 Node API 伺服器
├─ order.json # 存訂單資料
├─ index.html
├─ src/
│ ├─ main.js
│ ├─ App.vue
│ ├─ components/
│ │ ├─ OrderList.vue
│ │ └─ AddOrder.vue
└─ package.json
App.vue
<template>
<h1>簡單飲料訂單</h1>
<AddOrder @order-added="loadOrders" />
<OrderList :orders="orders" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
import AddOrder from './components/AddOrder.vue'
import OrderList from './components/OrderList.vue'
const orders = ref([])
async function loadOrders() {
const res = await fetch('http://localhost:3000/api/orders')
orders.value = await res.json()
}
onMounted(loadOrders)
</script>
components/OrderList.vue
<template>
<section>
<h2>目前訂單</h2>
<ul>
<li v-for="o in orders" :key="o.id">
{{ o.name }} - {{ o.drink }}
</li>
</ul>
</section>
</template>
<script setup>
defineProps({
orders: { type: Array, default: () => [] }
})
</script>
components/AddOrder.vue
<template>
<section>
<h2>新增訂單</h2>
<form @submit.prevent="addOrder">
<input v-model="name" placeholder="名字" required />
<select v-model="drink" required>
<option disabled value="">選擇飲料</option>
<option>紅茶</option>
<option>綠茶</option>
</select>
<button type="submit">送出</button>
</form>
</section>
</template>
<script setup>
import { ref } from 'vue'
const emit = defineEmits(['order-added'])
const name = ref('')
const drink = ref('')
async function addOrder() {
await fetch('http://localhost:3000/api/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: name.value, drink: drink.value })
})
name.value = ''
drink.value = ''
emit('order-added') // 通知父層重新抓資料
}
</script>
async function addOrder() {
await fetch('http://localhost:3000/api/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: name.value, drink: drink.value })
})
}
fetch 其實是原生地javascript method所以不用裝套件就可以使用
我們可以直接來使用這個方法呼叫後端地api
整理概念如下表:
位置 | 作用 |
---|---|
fetch(url, options) |
以 HTTP 請求方式,從瀏覽器與後端 API 溝通。這裡對 http://localhost:3000/api/orders 發送一個 POST 請求。 |
method: 'POST' |
指定請求方法為 POST ,表示要新增資料。如果是 GET 則代表讀取資料。 |
headers |
告訴伺服器傳送資料的格式。Content-Type: application/json 代表 body 是 JSON。 |
body |
請求要送出的資料內容。用 JSON.stringify 把 JavaScript 物件 { name, drink } 轉成字串。 |
await |
等待 fetch 完成後再往下執行,確保資料成功送出。 |
今天的內容沒有很困難,主要是來驗證是否有成功抓到後端地資料
接者可以驗證一下後端地order.json有沒有資料塞進去
何時需要 API
當應用程式需要 永久保存資料 或 跨裝置交換資料 時,就必須與後端 API 溝通。
例如:儲存飲料訂單到伺服器或從伺服器取回訂單列表。
API 基本流程Request
→ Server
→ Database(order.json)
→ Response
。
order.json
核心技術
GET
/ POST
呼叫 API(無需安裝額外套件)實作架構
server.js
:簡易 Node.js + Express 後端,提供 /api/orders 的 GET
與 POST
兩個路由fetch
呼叫 API,把訂單送到伺服器或取得最新訂單列表並渲染小提醒
fetch
不會自動報錯,要檢查 res.ok
。headers
的 Content-Type
必須與後端的解析方式一致 (express.json()
)。cors()
。今天先學到這邊,明天我們再來拆解我們的飲料訂製系統
P.S 因為本篇主要還是會以vue前端為主,後端地部分著墨比較少~ 主要還是讓大家可以下載下來call api練習使用
如果希望我可以講解後端地設計或code也可以留言跟我說!!