# 第四週 - 課前影音 / 錄影回放:https://courses.hexschool.com/courses/enrolled/2574732 - 每日任務:Discord 上發布 - 討論頻道:https://discord.com/channels/801807326054055996/1258601572867379222 - 每週挑戰: - 一~三週:HackMD 上繳交 - 最後一週作業:https://rpg.hexschool.com/#/training/12062289980134006991 - RPG 程式勇者: - 課程捷徑 - 課程講義 - 最後一週作業繳交 - 提醒老師錄影 ### 額外課程介紹: - JS 直播班:https://www.hexschool.com/courses/js-training.html - JS&React 直播班:https://www.hexschool.com/courses/js-react-training.html - 今晚開放報名,限量 60 位,剩餘 28 位 ## 今日主要主題 - Router - Pinia ### Router - 路由是什麼(路由表概念) ![image](https://hackmd.io/_uploads/rkuCwZQj0.png) - 路由結構配置 → 基本頁面結構配置 - 如何配置 router 檔案 - router-view - router-link 連結方式 ## 路由設定要點: 原本是使用 createWebHistory,當選擇此模式會使得無法部署至 GitHub Pages 如果有辦法調整 Server 環境,則可以參考此[文件](https://router.vuejs.org/zh/guide/essentials/history-mode.html#HTML5-%E6%A8%A1%E5%BC%8F)的方法。 ```jsx import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), ... }) ``` 如果要部署至 GitHub Pages,則可以建議換成 **createWebHashHistory** 的模式。 ```jsx import { createRouter, createWebHashHistory } from 'vue-router' const router = createRouter({ history: createWebHashHistory(import.meta.env.BASE_URL), ... }) ``` ## 路由基本手法 1. 開新頁面 XxxView.vue 2. 撰寫路由表 router/index.js 3. 提供連結方法 routerLink ## 常見路由結構 1. 基本路由 2. 巢狀路由 → 主要用為版型重複運用 - 巢狀路由 → 巢狀連結 router/index.js ```jsx { path: '/nest-router', component: () => import('../views/NestRouter.vue'), children: [ // ... ] } ``` vue file ```jsx <template> <h1>巢狀路由</h1> <RouterView /> </template> ``` 3. 動態路由(本次作業不會用到,但業界常見) - 動態路由 → 動態參數 router/index.js ```jsx { path: '/:id', component: () => import('../views/DynamicRouter.vue') } ``` vue file ```jsx <script setup> import { useRoute } from 'vue-router' const route = useRoute() console.log('router:', route); const { id } = route.params; // 網址上的值 </script> ``` ## 路由方法與狀態 - 路由狀態 useRoute - [https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#响应路由参数的变化](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96) - 路由方法 useRouter - [https://router.vuejs.org/zh/guide/advanced/composition-api.html#在-setup-中访问路由和当前路由](https://router.vuejs.org/zh/guide/advanced/composition-api.html#%E5%9C%A8-setup-%E4%B8%AD%E8%AE%BF%E9%97%AE%E8%B7%AF%E7%94%B1%E5%92%8C%E5%BD%93%E5%89%8D%E8%B7%AF%E7%94%B1) - 方法轉頁 - 404 ```jsx { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }, ``` - router.push(), back() - default link ``` { path: '*', redirect: '/', }, ``` ## 定義自己的路由配置 1. 請先定好完整路由架構 2. 將路由配置對應所有頁面,開發順序: 1. 先開頁面檔案 2. 撰寫路由配置 3. 補上 router-link - 登入頁面 /login (不驗證) - 前端頁面 (需驗證) - todo ## 補充:pathMatch 404 頁面:https://router.vuejs.org/guide/essentials/dynamic-matching#Catch-all-404-Not-found-Route ## Pinia ### 環境 環境起手式 ```jsx npm install pinia ``` 在 main.js 中加入以下 ```jsx import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const pinia = createPinia() const app = createApp(App) app.use(pinia) app.mount('#app') ``` 官方提醒:https://pinia.vuejs.org/zh/getting-started.html#when-should-i-use-a-store ### 引入 Store 1. 建立儲存空間 建立檔案 `stores/xxxx.js` 開始建立一個 store,store 撰寫方式與 composition API 無異。 ```jsx import { ref, computed } from 'vue' import { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', () => { const count = ref(0) const doubleCount = computed(() => count.value * 2) function increment() { count.value++ } return { count, doubleCount, increment } }) ``` 1. 在元件中引入 Store(完成) ```jsx <script setup> import { useCounterStore } from './store/countStore'; const countStore = useCounterStore() </script> <template> <p>{{ countStore.count }} / {{ countStore.doubleCount }}</p> <button @click="countStore.increment">++</button> </template> ``` 1. 解構屬性 ```jsx <script setup> import { useCounterStore } from '@/store/countStore'; import { storeToRefs } from 'pinia'; const counterStore = useCounterStore() // 非函式的值需要使用 storeToRefs const { count, doubleCount } = storeToRefs(counterStore) // 函式則不需要 const { increment } = counterStore </script> <template> <p>{{ count }} / {{ doubleCount }}</p> <button @click="increment">++</button> </template> ``` 1. 在 Pinia Store 中導入其他 Composition API 方法 ```jsx import { useRouter } from 'vue-router' export const useCounterStore = defineStore('counter', () => { const router = useRouter() function xxxx() { router.push('/') } return { xxxx } }) ``` ## 最終任務: - 設計稿:https://www.figma.com/design/MFSk8P5jmmC2ns9V9YeCzM/TodoList?node-id=0-1&t=KzEgeE3s3r6JIPh6-1 - CSS 範例:https://codepen.io/hexschool/pen/qBzEMdm - 同時挑戰證書任務: - [最終挑戰 - Todolist 新手證書任務](https://rpg.hexschool.com/#/tasks/12062289980169123704?preview=1) - [最終挑戰 - Todolist API 整合證書任務](https://rpg.hexschool.com/#/tasks/12062289980139618730?preview=1) > 提醒: > 最終證書作業繳交截止日:9/8(日) 完課證書發送時間:9/20(五)前 影音觀看期限:直播錄影將為您保留半年,期限為 2025/03/31