# 23. TodoList 路由模組

Vue todo list

# 關於 todo list

統整前面學到的觀念,製作 todo list 。

# 功能

  • 能新增事項
  • 能刪除事項,並跳出 alert 提醒。
  • 單擊事項能修改完成狀態。
  • 雙擊事項能修改事項內容。
  • 切換路由能陳列對應狀態的事項。
  • 將資料保存到 localStorage。

# 作法

  • 使用 component 建立區塊
  • 使用 Vuex store 存放資料

# 起始架構

使用 Vue CLI,並安裝以下依賴:

  • vue-router
  • vuex
  • vuex-router-syne (opens new window)
    • 將 Vue Router 同步為 Vuex state 的一部分。
    • 這個套件只是讓開發者能方便讀取 $route 的內容。修改仍需透過 Vue Router 而非 Vuex。

# 安裝 vuex-router-sync

# 安裝

可在終端機輸入 vue ui,從 UI 介面的 「依賴」 搜尋 "vuex-router-sync" 下載並安裝。

# 使用

安裝好 "vuex-router-sync" 之後,到 "main.js" 進行以下修改:

//- main.js

import { createApp } from "vue";
import App from "./App.vue";
import { sync } from 'vuex-router-sync' // 引入 vuex-router-sync
import router from "./router";
import store from "./store";

sync(store, router) // 同步 router 和 store
createApp(App).use(store).use(router).mount("#app");

# 原理

  • 這個套件會在 store 增加一個名為 route 的模組,用來表示目前路由的狀態。
store.state.route.path   // current path (字串)
store.state.route.params // current params (物件)
store.state.route.query  // current query (物件)
  • 切換路由時,store 的狀態會被更新。
  • store.state.route 是不能修改的,因為該值取自 URL,無法修改該值去觸發瀏覽器的導航行為。
  • 可以透過以下方法去修改路由:
    • $router.push()
    • $router.go()
    • $router.push({query: {...}}):更新目前路徑的 query 字串。

# 使用路徑篩選事項

在這個範例,我們會使用 router 去篩選出符合的事項。因此,我們將 router 中的 routes 改為:

//- router/index.js

import { createRouter, createWebHistory } from "vue-router";

const routes = [
  {
    path: "/all",     // 全部事項
    name: "all",
  },
  {
    path: "/active",  // 未完成事項
    name: "active",
  },
  {
    path: "/complete", // 已完成事項
    name: "complete",
  },
  {
    path: "*",
    redirect: "/all"  // 如果是其他參數,則重新導到 all
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

相對地,我們也要在 "App.vue" 修改路徑及其名稱:

//- App.vue

<template>
  <div id="nav">
    <router-link to="/all">全部</router-link> |
    <router-link to="/acitve">未完成</router-link> | 
    <router-link to="/complete">已完成</router-link>
  </div>
  <router-view />
</template>

沒用到的 .vue 檔案和 component 檔案就先刪掉,另外建立需要的模組。

WARNING

補充: 從 Vue 2.x 遷移到 Vue 3.x,Vue Router 移除了 * ,改用客製化的 regex 參數定義所有路由。

const routes = [
  // pathMatch 是参数的名称,例如,跳转到 /not/found 会得到
  // { params: { pathMatch: ['not', 'found'] } }
  // 这要归功于最后一个 *,意思是重复的参数,如果你
  // 打算直接使用未匹配的路径名称导航到该路径,这是必要的
  { path: '/:pathMatch(.*)*', name: 'not-found', component: NotFound },
  // 如果你省略了最后的 `*`,在解析或跳转时,参数中的 `/` 字符将被编码
  { path: '/:pathMatch(.*)', name: 'bad-not-found', component: NotFound },
]

參考:删除了 *(星标或通配符)路由 (opens new window)

WARNING

補充: 如果 Vue router 沒有設定 component ,瀏覽器執行後報錯,可在路由中設定 component: {render: (e) => e("router-view")}。例如:

const routes = [
  {
    path: "/all",
    name: "all",
    component: {render: (e) => e("router-view")}
  },
  {
    path: "/active",
    name: "active",
    component: {render: (e) => e("router-view")}
  },
  {
    path: "/complete",
    name: "complete",
    component: {render: (e) => e("router-view")}
  },
  {
    path: "/:pathMatch(.*)*",
    redirect: "/all"
  },
];

參考:【Vue-router】解决父级路由不需要 component的情况 (opens new window)