---
# System prepended metadata

title: "\U0001F3C5 Day 8 - 動態路由與 404 錯誤頁面處理"
tags: [2024 Nuxt 直播班]

---

# 🏅 Day 8 - 動態路由與 404 錯誤頁面處理

## 今日學習目標

- 學習建立並使用動態路由
- 學習如何配置 404 **錯誤頁面**

## 前言

在 Day7 中，我們已學習了如何建立嵌套式路由，並在學習範例中構建了如下圖所示的結構。在 `/pages/product` 資料夾下新增了 `productA.vue`  與  `productB.vue` 。
今天的學習將基於 Day7 的範例，將 `productA.vue` 和 `productB.vue` 轉換為動態路由的方式來進行管理。同學可以下載 Day7 的 [範例](https://github.com/jasonlu0525/nuxt3-live-example/tree/day7-nested-router) 以便進行學習。

![image](https://hackmd.io/_uploads/Byov5Dnbyx.png)


## 動態路由

在嵌套式路由的範例中，使用了靜態路由來處理 `productA.vue` 和 `productB.vue` 的結構，每個產品內頁都對應一個元件，如果這些元件中有大量程式碼重複，會導致代碼冗餘和維護困難。

為了解決這個問題，可以改成使用**動態路由**。動態路由通過 URL 參數來控制頁面顯示，不需為每個產品建立元件。如此一來就只需要用一個共用的元件，根據 URL 參數變化來顯示對應的產品內容。

### 建立方式

步驟一. 使用中括號 `[ ]` 來命名動態路由，並在中括號內填入動態路由的名稱。以 `/pages/product/productA.vue`  與  `/pages/product/productB.vue`  這兩支檔案為例，可以將它們合併為 `product/[id].vue` ( 如下圖 ) ，其中 `id` 為動態路由的名稱，後續取得動態路由的資訊將會使用到 `id` 這個名稱。

![image](https://hackmd.io/_uploads/SyYK5wnbJe.png)


步驟二. 在 `product/[id].vue`  可以使用路由  `useRoute()` 方法的 `params` 屬性，以動態路由的名稱 `id` 取得動態的 URL 參數。例如進入 `/product/productA` 路徑可以在 `[id].vue` 中使用 `params.id` 來取得路由的 `productA` 字串。

```html
<!-- /pages/product/[id].vue -->

<script setup>
// Auto Imports
const route = useRoute();

// 獲取路由中的動態參數
// 例如 : 路由路徑為 /product/productA ， route.params 為 { id: 'productA'}
// { id: 'productA'}
console.log(route.params);
</script>

<template>
  <h2>產品內頁 {{ route.params.id }}</h2>
</template>

<style scoped></style>

```

## 404 錯誤頁面

### 匹配所有層級的路由

在 Nuxt3 中，`[...slug].vue` 用於匹配特定路徑下所有層級的路由。當 URL 沒有匹配到相對應的路由時，會被 [...slug].vue  捕捉。以下方的路由結構為例，`/pages/product/[...slug].vue` 會匹配 `/product` 路徑下的所有路由。如果 URL 為 `/product/productA/info` ，由於沒有匹配到對應的 .vue 檔案，因此會匹配到  `/pages/product/[...slug].vue`。

```jsx
/pages
  ├── product
  │   ├── [id].vue
  │   ├── index.vue
  │   └── [...slug].vue
  ├── index.vue
  └── product.vue
```

`/pages/product/[...slug].vue` 檔案內容如下。進入 `[...slug].vue` 之後，可以通過 `route.params` 獲取動態路由參數 `slug`  的值。`slug`  參數是一個陣列，表示路徑中的每一層。例如對於　`/product/productA/info` 路徑，`route.params.slug` 的值為 `[ "productA", "info" ]`。

```html
<!-- /pages/product/[...slug].vue -->
<script setup>
const route = useRoute();
</script>

<template>
  <p>匹配到的 Params:{{ route.params.slug }}</p>
  <p>每個陣列元素對應一個層級</p>
</template>
```

關於更多  `[...slug].vue` 的資訊可以閱讀官方文件 : [**Catch-all Route**](https://nuxt.com/docs/guide/directory-structure/pages#catch-all-route)

### 建立 404 Not Found 頁面

理解了 `[...slug].vue` 的作用後，我們可以利用它來實作全站的 404 頁面。只需在 `./pages` 目錄下建立 `[...slug].vue`，並使用 `setResponseStatus()` 設定 HTTP 404 狀態碼。這樣，所有未匹配到的路由請求都將由此頁面處理。

```html
<!-- /pages/[...slug].vue -->
<script setup>
const route = useRoute();
const event = useRequestEvent(); // 獲取當前請求的事件

// 設定 HTTP 404 狀態碼
setResponseStatus(event, 404);
</script>

<template>
  <h1>404 Not Found</h1>
   <p>你所請求的頁面：{{ route.params.slug.join('/') }}，不存在。</p>
</template>

<style scoped>
h1 {
  color: red;
  text-align: center;
}
p {
  text-align: center;
}
</style>
```


<br>

> 今日學習的[範例 Code - 資料夾: day8-dynamic-router-example](https://github.com/hexschool/nuxt-daily-tasks-2024) 

## 題目
請 fork 這一份 [模板](https://github.com/jasonlu0525/nuxt3-live-question/tree/day8-dynamic-router)，接續 Day7 嵌套式路由的問題，實作房型詳細頁面的動態路由 :

- 將 `pages/room/_id.vue` 調整成房型內頁的動態路由。
- 在 `pages/room/index.vue` 的房型列表中，點擊房型後能夠進入房型內頁。進入房型內頁後，透過動態路由的網址參數 [串接 `/api/v1/rooms/{id}` 這支API](https://nuxr3.zeabur.app/swagger/#/Rooms%20-%20%E6%88%BF%E5%9E%8B/get_api_v1_rooms__id_) 來取得房型詳細資料。可以使用  `fetch` 或 `axios` 來串接 API。
- 取得房型資料後，將資料內容渲染在畫面上。畫面的 HTML 、CSS 已有在 `pages/room/_id.vue`  提供。
- 將 pages/notfound.vue 調整成全站的 404 頁面。畫面的 HTML 和 CSS 已經在 `pages/notfound.vue` 中提供。請在 `{{ page }}` 中渲染當前訪問頁面的路由路徑，並提供一個返回首頁的連結。

## 回報流程

將答案上傳至 GitHub 並複製 GitHub  repo 連結貼至底下回報就算完成了喔 !
解答位置請參考下圖（需打開程式碼的部分觀看）

![](https://i.imgur.com/vftL5i0.png)

<!--   

解答: https://github.com/jasonlu0525/nuxt3-live-answer/tree/day8-dynamic-router

-->


回報區
---
| #   | Discord | Github / 答案 |
| --- | ----- | ----- |
|1|眼睛|[GitHub](https://github.com/Thrizzacode/nuxt3-live-question/tree/day8-dynamic-router)|
|2|keivnhes|[Github](https://github.com/kevinhes/nuxt-daily-mission/tree/day8)|
|3|LinaChen|[Github](https://github.com/Lina-SHU/nuxt3-live-question)|
| 4 | Steven | [GitHub](https://github.com/y7516552/nuxt3-live-question/tree/day8) |
| 5 | dragon | [GitHub](https://github.com/peterlife0617/2024-nuxt-training-homework01/tree/feature/day08) |
| 6 | NeiL | [GitHub](https://github.com/Neil10241126/nuxt-demo/tree/day8-dynamic-router) | 
| 7 | MY | [GitHub](https://github.com/ahmomoz/nuxt3-live-question/tree/day8-dynamic-router-hw) | 
| 8 | Tough life | [GitHub](https://github.com/hakuei0115/Nuxt_testing) | 
| 9 | Jim Lin | [GitHub](https://github.com/junhoulin/Nuxt3-hw-day8) | 
|10| Ariel | [GitHub](https://github.com/Ariel0508/nuxtday6/tree/nuxtday8) |
|11|松鼠|[GitHub](https://github.com/meishinro/dailyMissionEight)|
|12|小木馬|[GitHub](https://github.com/wern0531/Nuxt-test-day8)|
|13|Ming|[GitHub](https://github.com/ming77712/2024-nuxt3-daily05)|
| 14 |hsin yu | [GitHub](https://github.com/dogwantfly/nuxt3-daily-task-live-question/tree/day8-dynamic-router) | 
| 15 | wei_Rio | [GitHub](https://github.com/wei-1539/nuxtDaily7) | 
| 16 | Stan | [GitHub](https://github.com/haoxiang16/nuxt3-live-question/tree/day8-dynamic-router) | 
| 17 | runweiting | [GitHub](https://github.com/runweiting/2024-NUXT-Task/tree/day8) | 
| 18 | Rocky | [GitHub](https://github.com/WuRocky/Nuxt-Day8-Catch-all-Route.git) | 
| 19 | Fabio | [GitHub](https://github.com/fabio7621/nuxt3-live-question-d2/tree/nuxt3-live-day8) |
| 20 | barry1104 | [GitHub](https://github.com/barrychen1104/nuxt3-live-question/tree/day8-dynamic-router) |
| 21 | tanuki狸 | [GitHub](https://github.com/tanukili/Nuxt-2024-week01-2/tree/day8-dynamic-router) | 
| 22 | hannahTW | [GitHub](https://github.com/hangineer/nuxt3-live-question/tree/day8-dynamic-router) | 
| 23 | Nielsen | [GitHub](https://github.com/asz8621/nuxt3-daily-task/tree/day8-dynamic-router) | 
| 24 | 阿塔 | [GitHub](https://github.com/QuantumParrot/2024-Hexschool-Nuxt-Camp-Daily-Task) | 
|25|好了啦|[GitHub](https://github.com/ZhangZJ0906/nuxt-live)|
|26|Johnson|[GitHub](https://github.com/tttom3669/2024_hex_nuxt_daily/tree/day8-dynamic-router)|
| 27 | lidelin | [GitHub](https://github.com/Lide/nuxt3-live-question/tree/day8-dynamic-router) | 
| 28 | bb | [GitHub](https://github.com/wicebing/nuxt3-live-question/tree/day8-dynamic-router) |


<!-- 快速複製
 | --- | ----- | [GitHub]() | 
-->
