串接後端資料
以下是一個使用 **Vue 3 + Fetch API** 的完整範例,會從指定網址取得商品資料,並顯示在網頁上。
將以下內容存成 `index.html` 後,直接用瀏覽器開啟即可:
```html
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue 商品列表</title>
<!-- 載入 Vue 3 -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
body {
margin: 0;
padding: 30px;
font-family: Arial, "Microsoft JhengHei", sans-serif;
background: #f5f5f5;
color: #333;
}
.container {
max-width: 1100px;
margin: auto;
}
h1 {
text-align: center;
margin-bottom: 30px;
}
.status {
text-align: center;
padding: 20px;
color: #666;
}
.error {
color: #d93025;
}
.product-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 20px;
}
.product-card {
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
transition: transform 0.2s;
}
.product-card:hover {
transform: translateY(-4px);
}
.product-image {
width: 100%;
height: 180px;
object-fit: cover;
background: #eee;
}
.product-content {
padding: 16px;
}
.product-name {
margin: 0 0 10px;
font-size: 20px;
}
.product-description {
color: #666;
line-height: 1.6;
min-height: 50px;
}
.price {
color: #e53935;
font-size: 20px;
font-weight: bold;
margin-top: 12px;
}
</style>
</head>
<body>
<div id="app" class="container">
<h1>商品列表</h1>
<div v-if="loading" class="status">
資料載入中...
</div>
<div v-else-if="error" class="status error">
{{ error }}
</div>
<div v-else-if="products.length === 0" class="status">
找不到商品資料
</div>
<div v-else class="product-list">
<div
v-for="product in products"
:key="product.id"
class="product-card"
>
<img
v-if="product.image"
:src="product.image"
:alt="getProductName(product)"
class="product-image"
/>
<div v-else class="product-image"></div>
<div class="product-content">
<h2 class="product-name">
{{ getProductName(product) }}
</h2>
<p class="product-description">
{{ product.description || '目前沒有商品描述' }}
</p>
<div class="price">
{{ formatPrice(product.price) }}
</div>
</div>
</div>
</div>
</div>
<script>
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const products = ref([]);
const loading = ref(true);
const error = ref('');
const apiUrl =
'https://cwpeng.github.io/live-records-samples/data/products.json';
async function fetchProducts() {
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP 錯誤:${response.status}`);
}
const data = await response.json();
// API 可能直接回傳陣列,
// 也可能回傳 { products: [...] }
products.value = Array.isArray(data)
? data
: data.products || [];
} catch (err) {
error.value = `無法取得商品資料:${err.message}`;
} finally {
loading.value = false;
}
}
function getProductName(product) {
return product.name || product.title || '未命名商品';
}
function formatPrice(price) {
if (price === undefined || price === null) {
return '價格未提供';
}
return Number(price).toLocaleString('zh-TW', {
style: 'currency',
currency: 'TWD',
maximumFractionDigits: 0
});
}
onMounted(() => {
fetchProducts();
});
return {
products,
loading,
error,
getProductName,
formatPrice
};
}
}).mount('#app');
</script>
</body>
</html>
```
### 程式重點
使用 `fetch()` 呼叫後端資料:
```javascript
const response = await fetch(apiUrl);
const data = await response.json();
products.value = data;
```
使用 `v-for` 將商品逐筆顯示:
```html
<div v-for="product in products" :key="product.id">
{{ product.name }}
</div>
```
使用 `v-if` 顯示載入中、錯誤或沒有資料的狀態:
```html
<div v-if="loading">資料載入中...</div>
<div v-else-if="error">{{ error }}</div>
```
此範例使用 Vue CDN,因此不需要安裝 Node.js 或建立 Vite 專案即可執行。
相關學習地圖、教學課程
F2E 網站前端工程