本文最后更新于29 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
Vue 进阶学习详细步骤(从 Router 到实战项目)
以下是针对 Vue Router、Pinia、组件库、Axios 的分阶段学习步骤,每个阶段都包含「核心概念→实操练习→常见问题」,最后通过「用户管理系统」实战串联所有知识点,确保学完能落地。
一、第一阶段:学习 Vue Router(单页应用路由核心)
1. 前置准备:明确学习目标
掌握「页面切换、路由传参、权限控制」,能实现类似 “首页→列表页→详情页” 的跳转逻辑,理解单页应用(SPA)的路由原理。
2. 步骤 1:安装并初始化 Vue Router
(1)安装依赖(在 Vue 项目根目录执行)
bash
# Vue 3 对应 Vue Router 4(必须安装 4.x 版本)
npm install vue-router@4
(2)创建路由目录结构
在 src
下新建 router
文件夹,创建 index.js
(路由配置文件),目录结构如下:
plaintext
src/
├─ router/
│ └─ index.js # 路由配置
├─ views/ # 页面级组件(区别于 components 通用组件)
│ ├─ Home.vue # 首页
│ ├─ UserList.vue # 用户列表页
│ └─ UserDetail.vue # 用户详情页
└─ App.vue
(3)编写基础路由配置(src/router/index.js)
javascript
运行
// 1. 导入 Vue Router 核心函数和页面组件
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import UserList from '../views/UserList.vue'
import UserDetail from '../views/UserDetail.vue'
// 2. 定义路由规则:path(路径)→ component(对应页面)
const routes = [
{
path: '/', // 根路径
name: 'Home', // 路由名称(可选,用于编程式导航)
component: Home // 对应页面组件
},
{
path: '/user-list',
name: 'UserList',
component: UserList
},
{
path: '/user-detail/:id', // 动态路由(:id 是参数,用于传用户 ID)
name: 'UserDetail',
component: UserDetail
}
]
// 3. 创建路由实例
const router = createRouter({
history: createWebHistory(), // 无 # 的路由模式(推荐)
routes // 传入路由规则
})
// 4. 导出路由实例(供 main.js 引入)
export default router
(4)在 main.js 中挂载路由
javascript
运行
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 引入路由配置
// 挂载路由到 App
createApp(App).use(router).mount('#app')
(5)在 App.vue 中添加路由出口和导航
vue
<template>
<div>
<!-- 1. 路由导航(类似 a 标签,不会刷新页面) -->
<nav>
<router-link to="/">首页</router-link> |
<router-link to="/user-list">用户列表</router-link>
</nav>
<!-- 2. 路由出口:匹配的页面组件会渲染到这里 -->
<router-view />
</div>
</template>
3. 步骤 2:核心功能实操(逐个突破)
(1)两种导航方式(声明式 + 编程式)
- 声明式导航:用
<router-link>
(已在上面实现,适合静态导航栏)。 - 编程式导航:用 useRouter 函数(适合按钮点击等动态跳转),示例(在 UserList.vue 中):vue<template>
<div>
<h1>用户列表</h1>
<!– 点击跳转到详情页,传用户 ID=123 –>
<button @click=”goToDetail(123)”>查看用户 123 详情</button>
</div>
</template>
<script setup>
import { useRouter } from ‘vue-router’ // 导入路由钩子
const router = useRouter() // 获取路由实例
// 编程式导航函数
const goToDetail = (userId) => {
// 方式 1:用 path + params(需配合动态路由)
router.push({ path: `/user-detail/${userId}` })
// 方式 2:用 name + params(需路由配置有 name)
// router.push({ name: ‘UserDetail’, params: { id: userId } })
}
</script>
(2)路由传参与接收(动态路由参数)
在 UserDetail.vue 中接收 :id
参数:
vue
<template>
<div>
<h1>用户详情</h1>
<p>当前用户 ID:{{ userId }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router' // 注意:useRoute 是获取当前路由信息
const route = useRoute()
// 接收动态路由参数(route.params.参数名)
const userId = route.params.id
</script>
(3)嵌套路由(实现 “页面内子页面”)
比如在 UserList 页面内嵌套 “用户列表” 和 “用户统计” 子页面,步骤:
- 在 UserList.vue 中添加 <router-view>(子路由出口):vue<template>
<div>
<h1>用户列表</h1>
<!– 子路由导航 –>
<div>
<router-link to=”/user-list/list”>列表视图</router-link> |
<router-link to=”/user-list/stat”>统计视图</router-link>
</div>
<!– 子路由出口 –>
<router-view />
</div>
</template> - 在 router/index.js 中配置嵌套路由(用 children 字段):javascript运行const routes = [
// …其他路由
{
path: ‘/user-list’,
name: ‘UserList’,
component: UserList,
// 嵌套子路由
children: [
{
path: ‘list’, // 子路径(完整路径:/user-list/list)
component: () => import(‘../views/UserList/List.vue’) // 懒加载组件
},
{
path: ‘stat’, // 完整路径:/user-list/stat
component: () => import(‘../views/UserList/Stat.vue’)
},
{
path: ”, // 默认子路由(访问 /user-list 时显示)
redirect: ‘list’ // 重定向到 list 子路由
}
]
}
]
(4)路由守卫(权限控制)
比如 “未登录用户不能访问用户列表”,用全局前置守卫实现: 在 router/index.js 中添加:
javascript
运行
// 全局前置守卫:每次路由跳转前执行
router.beforeEach((to, from, next) => {
// to:要跳转到的路由;from:从哪个路由来;next:是否允许跳转
// 1. 定义需要登录的路由白名单
const needLoginRoutes = ['UserList', 'UserDetail']
// 2. 模拟是否登录(实际项目中从 Pinia/本地存储获取)
const isLogin = localStorage.getItem('isLogin') === 'true'
// 3. 判断:若要访问需要登录的路由且未登录,跳转到首页
if (needLoginRoutes.includes(to.name) && !isLogin) {
next({ path: '/' }) // 强制跳转首页
} else {
next() // 允许跳转
}
})
4. 步骤 3:巩固练习
- 实现 “首页→商品列表→商品详情” 的路由跳转,包含:
- 商品列表页用编程式导航跳转到详情页,传递商品 ID;
- 详情页接收 ID 并显示;
- 给 “商品详情” 路由添加守卫,要求必须从 “商品列表” 跳转才能访问(用
from
判断)。
二、第二阶段:学习 Pinia(全局状态管理)
1. 前置准备:明确学习目标
解决 “多个组件共享数据” 的问题(比如用户登录状态、购物车数据),理解 “状态→动作→响应式” 的逻辑,替代 Vue 2 的 Vuex。
2. 步骤 1:安装并初始化 Pinia
(1)安装依赖
bash
npm install pinia
(2)创建 Pinia 实例并挂载(main.js)
javascript
运行
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia' // 导入 Pinia
const app = createApp(App)
const pinia = createPinia() // 创建 Pinia 实例
// 挂载 Pinia 和路由
app.use(pinia).use(router).mount('#app')
(3)创建第一个 Store(状态容器)
在 src
下新建 stores
文件夹,创建 userStore.js
(用户相关状态):
javascript
运行
// 1. 导入 defineStore(定义 Store 的核心函数)
import { defineStore } from 'pinia'
// 2. 定义 Store:第一个参数是 Store 唯一 ID(必须唯一),第二个参数是配置
export const useUserStore = defineStore('user', {
// ① state:存储全局状态(类似组件的 data)
state: () => ({
isLogin: false, // 是否登录
userInfo: { // 用户信息
name: '',
id: '',
role: '' // 角色(普通用户/管理员)
}
}),
// ② actions:修改状态的函数(类似组件的 methods,支持异步)
actions: {
// 登录动作:接收用户信息参数,修改 state
login(userData) {
this.isLogin = true // 直接修改 state(Pinia 无需 mutations)
this.userInfo = userData
// 存储到本地存储,避免刷新页面丢失
localStorage.setItem('userInfo', JSON.stringify(userData))
localStorage.setItem('isLogin', 'true')
},
// 退出登录动作
logout() {
this.isLogin = false
this.userInfo = { name: '', id: '', role: '' }
localStorage.removeItem('userInfo')
localStorage.removeItem('isLogin')
},
// 异步动作:模拟从接口获取用户信息(配合 Axios 后续用)
async fetchUserInfo() {
// 实际项目中这里用 Axios 调用后端接口
const mockData = await new Promise(resolve => {
setTimeout(() => {
resolve({ name: '张三', id: '123', role: 'admin' })
}, 1000)
})
this.userInfo = mockData
this.isLogin = true
}
},
// ③ getters:计算属性(类似组件的 computed,缓存结果)
getters: {
// 拼接用户名称和角色
userDesc: (state) => {
return `${state.userInfo.name}(${state.userInfo.role})`
}
}
})
3. 步骤 2:核心功能实操
(1)在组件中使用 Store(登录案例)
创建 Login.vue 页面,实现登录并修改全局状态:
vue
<template>
<div>
<h1>登录页</h1>
<input v-model="username" placeholder="请输入用户名" />
<button @click="handleLogin">登录</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useUserStore } from '../stores/userStore' // 导入 Store
import { useRouter } from 'vue-router'
const username = ref('')
const userStore = useUserStore() // 获取 Store 实例
const router = useRouter()
// 登录按钮点击事件
const handleLogin = () => {
if (!username.value) return alert('请输入用户名')
// 调用 Store 的 login 动作,传递用户数据
userStore.login({
name: username.value,
id: '456',
role: 'user'
})
// 登录成功后跳转到用户列表
router.push('/user-list')
}
</script>
(2)在其他组件中共享状态(用户列表页)
在 UserList.vue 中显示登录用户信息:
vue
<template>
<div>
<h1>用户列表</h1>
<!-- 显示 Store 中的 getters 计算属性 -->
<p>当前登录用户:{{ userStore.userDesc }}</p>
<!-- 点击退出登录,调用 Store 的 logout 动作 -->
<button @click="userStore.logout">退出登录</button>
</div>
</template>
<script setup>
import { useUserStore } from '../stores/userStore'
const userStore = useUserStore() // 直接获取 Store 实例,共享状态
</script>
(3)修改状态的两种方式
- 直接修改(简单场景):javascript运行const userStore = useUserStore()
userStore.isLogin = true // 直接修改 state 属性 - 通过 actions 修改(复杂场景,推荐,便于统一管理):javascript运行// 在 Store 中定义 actions,组件中调用
userStore.login(userData)
4. 步骤 3:巩固练习
- 实现 “购物车 Store”,包含:
- state:
cartList
(购物车商品数组); - actions:
addCart
(添加商品)、removeCart
(删除商品)、clearCart
(清空购物车); - getters:
cartTotal
(计算购物车商品总数)、cartPrice
(计算购物车总金额); - 在 “商品详情页” 添加商品到购物车,在 “购物车页面” 显示并操作购物车。
- state: