# 第四週
- 課前影音 / 錄影回放: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
- 路由是什麼(路由表概念)

- 路由結構配置 → 基本頁面結構配置
- 如何配置 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