# 🏅 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]() | -->