下载工作台
前端框架精通

Vue Router 与 Pinia 实战

试读上半部分 · 解锁后可读全文

第 3 章 · Vue Router 与 Pinia 实战

本章目标:为 academy-demo-vue 接入 vue-router 多页面路由与 Pinia 全局状态;实现首页 / 课程列表 / 课程详情 / 待办四页;与 Fetch Mock 联调,对齐 ch16 毕业项目核心链路。

学时建议:4~5 小时

前置:完成本模块 ch01~ch02;熟悉 ch16 数据模型与 Mock 结构。


3.1 安装与项目结构

cd academy-demo-vue
npm install vue-router@4 pinia
src/
├── main.js
├── App.vue                    # <RouterView />
├── router/
│   └── index.js
├── stores/
│   ├── courses.js             # 课程列表、筛选
│   ├── favorites.js           # 收藏
│   └── userPrefs.js           # 主题、最近搜索
├── views/
│   ├── HomeView.vue
│   ├── CourseListView.vue
│   ├── CourseDetailView.vue
│   └── TodoView.vue
├── components/
│   ├── AppHeader.vue
│   ├── CourseCard.vue
│   └── CourseList.vue
└── api/
    └── client.js
模块职责
router/URL ↔ 视图映射、导航守卫
stores/跨页面共享状态
views/页面级组件(对应 ch16 各 html)
api/client.js统一 Fetch 封装

3.2 Vue Router 基础配置

// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'home',
    component: () => import('../views/HomeView.vue'),
    meta: { title: '首页' },
  },
  {
    path: '/courses',
    name: 'courses',
    component: () => import('../views/CourseListView.vue'),
    meta: { title: '课程列表' },
  },
  {
    path: '/courses/:id',
    name: 'course-detail',
    component: () => import('../views/CourseDetailView.vue'),
    props: true,
    meta: { title: '课程详情' },
  },
  {
    path: '/todo',
    name: 'todo',
    component: () => import('../views/TodoView.vue'),
    meta: { title: '学习计划' },
  },
  { path: '/:pathMatch(.*)*', redirect: '/' },
]

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes,
  scrollBehavior() {
    return { top: 0 }
  },
})

router.afterEach((to) => {
  document.title = `${to.meta.title ?? '页面'} · 贤紫技术学院`
})

export default router
// src/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
<!-- src/App.vue -->
<template>
  <AppHeader />
  <main class="main">
    <RouterView />
  </main>
  <footer class="site-footer">© 2026 贤紫优选</footer>
</template>

3.3 动态路由与导航

详情页通过 props: true 接收 :iduseRoute() 读参数,useRouter() 编程式跳转。AppHeaderRouterLink + router-link-active 高亮当前页。列表卡片:router.push({ name: 'course-detail', params: { id } })

无效 id 时 router.replace({ name: 'courses' })onMountedfetchAll()fetchChapters(id)


3.4 导航守卫

守卫触发时机典型用途
beforeEach全局跳转前鉴权、进度条
beforeEnter进入某路由前预加载数据
onBeforeRouteLeave组件内离开未保存提示
// router/index.js 片段
router.beforeEach((to, from, next) => {
  // 示例:详情页必须有 id
  if (to.name === 'course-detail' && !to.params.id) {
    next({ name: 'courses' })
    return
  }
  next()
})
<!-- TodoView.vue 离开守卫示例 -->
onBeforeRouteLeave((to, from, next) => {
  dirty.value && !confirm('待办未保存?') ? next(false) : next()
})

3.5 Pinia Store 设计

3.5.1 课程 Store

// src/stores/courses.js

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。