iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Vue.js

需求至上的 Vue 魔法之旅系列 第 12

Day 9 : 連接世界的魔法:API 溝通術

  • 分享至 

  • xImage
  •  

前言

在前幾天,我們已經學會如何用 Vue 建構出完整的前端互動應用,也成功拆解了組件。但這些功能目前都還停留在「瀏覽器的世界」。
今天我們要邁出關鍵的一步:學習與外部世界對話的魔法——HTTP Request,也就是大家常說的 Call API

為什麼要這樣做?

  • 如果你的程式只需要單機運作,例如計算機、離線計時器,其實可以不必後端。
  • 但如果你需要永久保存資料跨裝置同步與其他服務交換資訊,那就必須學會如何透過 API 與後端伺服器及資料庫連線。

我們會先用一張 HTTP 示意圖,幫助大家理解請求 (Request)回應 (Response) 的完整過程,然後分析使用者需求、建立 User Story,再到程式實作,完整體驗前端到後端的資料流。


一、需求拆解與分析

1. 使用者需求:為什麼要存到後端?

  • 單純前端執行的情境
    你的程式碼不需要永久保存或跨裝置傳輸資料,例如單機的待辦清單、計算機。這種情況可以直接打包成可執行檔或 PWA (Progressive Web App) 使用。

  • 需要後端的情境
    若需要:

    • 保存訂單或使用者資料
    • 與其他裝置同步
    • 做統計或報表分析
      ➜ 就必須把資料存到後端資料庫,並透過 API 提供資料交換。

結論:當系統要「儲存、整合或跨裝置交換資料」時,API 就是必修的魔法。


2. API 的意境:一場網路下單的比喻

以下示意圖可以幫助理解:
https://ithelp.ithome.com.tw/upload/images/20250926/20121052upQ9V2hiLX.png

  • Client User:就像網路下單的顧客
  • HTTP Methods (GET/POST):下單時選擇的動作,如「查詢訂單」(GET) 或「新增訂單」(POST)
  • HTTP Header (Token/Cookie):像是會員 ID 卡,用於驗證身份
  • Request Data (Body):你的客製化需求,例如紅茶去冰
  • Server & Database:後端伺服器和倉庫,負責存放和處理資料
  • Response:回傳送貨方式、出貨狀態以及實際資料,送到不同的收件人手中

更多HTTP API的介紹可以參考我去年python說明:
👉 我之前的後端教學文章python版


3. User Story

以我們的 飲料點單系統為例:

  • Story 1:取得訂單列表
    「作為使用者,我希望能看到目前所有訂單」
    → 對應 API:GET /api/orders
  • Story 2:新增一筆訂單
    「作為使用者,我希望可以新增一筆飲料訂單」
    → 對應 API:POST /api/orders

4. 時序圖 (Mermaid)

以下用 時序圖 來描述一個新增訂單的流程:

https://ithelp.ithome.com.tw/upload/images/20250926/20121052lKJlp7dJpo.png

二、程式實作

1. Vue 會用到的技術

  • 生命週期:如 onMounted 可用來在畫面初始化時發送 GET 請求
  • 狀態管理:使用 refreactive 管理 loadingerror 狀態
  • 事件處理:例如表單送出時觸發 submit 事件

2. Axios 與 API 呼叫範例

今天我們會簡單介紹前後端怎麼建立跟互相溝通

再把後端data(order.json)傳回前端

前端在把資料(訂單)送到後端

我們先建立在一個folder叫做basic server(用來存後端的程式碼跟資料檔)

  • 先用order.json當作資料庫存點餐內容
  • 我們已經有安裝nodejs了所以可以直接無痛啟用相關環境

order.json

[
  { "id": "1", "name": "Alice", "drink": "紅茶" },
  { "id": "2", "name": "Bob", "drink": "綠茶" }
]

這個當作我們的初始化data

(a) 簡易 Node.js 伺服器 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

https://ithelp.ithome.com.tw/upload/images/20250926/20121052zgpmpSZRcj.png

(b) Vue 呼叫 API 的範例

接下來我們可以用指令來創建一個新的前端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>

說明fetch

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 完成後再往下執行,確保資料成功送出。

https://ithelp.ithome.com.tw/upload/images/20250926/20121052G9XsBo6c7S.png

今天的內容沒有很困難,主要是來驗證是否有成功抓到後端地資料

接者可以驗證一下後端地order.json有沒有資料塞進去

https://ithelp.ithome.com.tw/upload/images/20250926/20121052XY9ZoftATK.png


重點複習

  • 何時需要 API
    當應用程式需要 永久保存資料跨裝置交換資料 時,就必須與後端 API 溝通。
    例如:儲存飲料訂單到伺服器或從伺服器取回訂單列表。

  • API 基本流程
    RequestServerDatabase(order.json)Response

    • 前端送出請求
    • 後端接收並更新/讀取 order.json
    • 回傳結果給前端
  • 核心技術

    • Vue:元件拆分、狀態管理、表單輸入綁定
    • fetch:原生 GET / POST 呼叫 API(無需安裝額外套件)
  • 實作架構

    • server.js:簡易 Node.js + Express 後端,提供 /api/ordersGETPOST 兩個路由
    • Vue 前端:使用 fetch 呼叫 API,把訂單送到伺服器或取得最新訂單列表並渲染
  • 小提醒

    • fetch 不會自動報錯,要檢查 res.ok
    • headersContent-Type 必須與後端的解析方式一致 (express.json())。
    • 開發環境若前端與後端不同網域,需要在後端啟用 cors()

今天先學到這邊,明天我們再來拆解我們的飲料訂製系統

P.S 因為本篇主要還是會以vue前端為主,後端地部分著墨比較少~ 主要還是讓大家可以下載下來call api練習使用

如果希望我可以講解後端地設計或code也可以留言跟我說!!/images/emoticon/emoticon07.gif


上一篇
Day8 : 讓你接受我的控制:受控表單設計
下一篇
Day 9.5 — 讓通訊更好用的魔法:用 Axios 封裝飲料訂單 CRUD
系列文
需求至上的 Vue 魔法之旅13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言