当前位置: 首页 > news >正文

Vue 3项目中的路由管理和状态管理系统

核心概念理解

1. 整体架构关系

这两个文件构成了Vue应用的导航系统状态管理系统

  • Router(路由):控制页面跳转和URL变化
  • Store(状态):管理全局数据和用户状态
  • 两者协同工作实现权限控制
2. 数据流向
用户操作 → 路由跳转 → 路由守卫检查 → 读取Store状态 → 决定是否允许访问

关键交互点分析

Router 与 Store 的协作
  1. 路由守卫中使用Store

    • store.getters.token - 检查登录状态
    • store.getters.isAdmin - 检查管理员权限
  2. 三层权限控制

    • 第一层requiresAuth - 需要登录
    • 第二层requiresAdmin - 需要管理员权限
    • 第三层:后端API验证(token验证)

实际应用场景

用户登录流程
  1. 用户在Login.vue输入账号密码
  2. 调用 store.dispatch('login', formData)
  3. Store发送API请求到后端
  4. 成功后存储token、user、role到Store和localStorage
  5. Router自动跳转到dashboard
  6. 后续访问带token请求后端API
用户登出流程
  1. 用户点击登出按钮

  2. 调用 store.dispatch('logout')

  3. 清除所有用户状态

  4. Router守卫检测到无token

  5. 自动重定向到登录页

  6. 安全性增强

// 可以添加token过期检查
const isTokenExpired = (token) => {// 解析JWT token获取过期时间const payload = JSON.parse(atob(token.split('.')[1]));return Date.now() >= payload.exp * 1000;
};
  1. 用户体验优化
// 记住用户要访问的页面
router.beforeEach((to, from, next) => {if (to.meta.requiresAuth && !token) {// 保存目标路径sessionStorage.setItem('redirectPath', to.fullPath);next('/login');}
});
  1. 错误处理完善
// 在actions中添加更详细的错误处理
async login({ commit }, loginForm) {commit('SET_LOADING', true); // 添加加载状态try {// ... 登录逻辑} catch (error) {commit('SET_ERROR', error.message);throw error;} finally {commit('SET_LOADING', false);}
}
  1. 路由懒加载原理

    • 使用动态import()实现代码分割
    • 只在需要时加载对应组件
    • 减少首屏加载时间
  2. Vuex持久化策略

    • localStorage:简单但有安全风险
    • sessionStorage:关闭浏览器后失效
    • Cookie:可设置httpOnly提高安全性
    • IndexedDB:适合大量数据存储
  3. 路由守卫类型

    • 全局守卫:beforeEach、beforeResolve、afterEach
    • 路由独享守卫:beforeEnter
    • 组件内守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

这两个文件是Vue应用的基础设施

// ==========================================
// Vue Router 路由配置文件详解
// 文件路径: src/router/index.js
// ==========================================/*** 背景知识:* Vue Router 是 Vue.js 的官方路由管理器* 它用于构建单页面应用(SPA),实现页面间的导航* 主要功能包括:路由映射、嵌套路由、路由守卫、懒加载等*/// 1. 导入必要的依赖
import { createRouter, createWebHistory } from "vue-router";  // Vue Router 4.x 的核心函数
import store from "@/store";  // Vuex 状态管理,用于获取用户登录状态
import { ElMessage } from "element-plus";  // Element Plus UI库的消息提示组件/*** 2. 路由配置数组* 每个路由对象包含以下属性:* - path: URL路径* - name: 路由名称(用于编程式导航)* - component: 对应的Vue组件* - meta: 路由元信息(自定义数据)* - redirect: 重定向目标* - children: 子路由数组*/
const routes = [// 登录页路由{path: "/login",  // 访问路径name: "Login",   // 路由名称// 路由懒加载:只有访问该路由时才加载组件,优化首屏加载速度component: () => import("@/views/Login.vue"),meta: { requiresAuth: false  // 元信息:标记该页面不需要登录验证},},// 主布局路由(包含所有需要登录的页面){path: "/",  // 根路径name: "Layout",component: () => import("@/views/Layout.vue"),  // 布局组件(通常包含导航栏、侧边栏等)redirect: "/dashboard",  // 访问根路径时自动重定向到仪表盘meta: { requiresAuth: true  // 需要登录验证},// 嵌套路由:这些页面都会渲染在Layout组件的<router-view>中children: [// 仪表盘页面{path: "dashboard",  // 实际路径为 /dashboardname: "Dashboard",component: () => import("@/views/Dashboard.vue"),meta: { title: "仪表盘",  // 页面标题(可用于动态设置浏览器标题)icon: "Odometer"  // 图标名称(用于菜单显示)},},// 用户管理页面(仅管理员可访问){path: "users",name: "Users",component: () => import("@/views/UserManagement.vue"),meta: { title: "用户管理",icon: "User",requiresAdmin: true  // 特殊权限标记:需要管理员权限},},// 个人信息页面{path: "profile",name: "Profile",component: () => import("@/views/Profile.vue"),meta: { title: "个人信息",icon: "UserFilled"},},],},// 404 通配符路由(必须放在最后){path: "/:pathMatch(.*)*",  // Vue Router 4.x 的通配符语法redirect: "/login",  // 所有未匹配的路径都重定向到登录页},
];/*** 3. 创建路由实例*/
const router = createRouter({// 使用 HTML5 History 模式(URL中没有#号,更美观)// 需要服务器配置支持,否则刷新页面会404history: createWebHistory(process.env.BASE_URL),routes,  // 路由配置
});/*** 4. 全局前置守卫(Navigation Guards)* 在每次路由跳转前执行,用于权限验证* * 参数说明:* - to: 即将进入的目标路由对象* - from: 当前导航正要离开的路由对象* - next: 必须调用的函数,用于解析钩子*/
router.beforeEach((to, from, next) => {// 从 Vuex store 获取用户 token(判断是否登录)const token = store.getters.token;// 场景1:访问需要登录的页面,但用户未登录if (to.meta.requiresAuth && !token) {ElMessage.warning("请先登录");  // 显示提示消息next("/login");  // 重定向到登录页} // 场景2:访问需要管理员权限的页面,但用户不是管理员else if (to.meta.requiresAdmin && !store.getters.isAdmin) {ElMessage.error("权限不足");next("/dashboard");  // 重定向到仪表盘} // 场景3:已登录用户访问登录页(避免重复登录)else if (to.path === "/login" && token) {next("/dashboard");  // 直接跳转到仪表盘} // 场景4:正常访问else {next();  // 放行,继续导航}
});/*** 5. 导出路由实例* 在 main.js 中需要引入并注册到 Vue 应用中*/
export default router;/*** 使用示例:* * 1. 在组件中进行路由跳转:*    this.$router.push('/users')  // 编程式导航*    <router-link to="/profile">个人信息</router-link>  // 声明式导航* * 2. 获取路由参数:*    this.$route.params.id  // 获取动态路由参数*    this.$route.query.name  // 获取查询参数* * 3. 路由守卫的执行顺序:*    全局前置守卫 → 路由独享守卫 → 组件内守卫 → 全局后置钩子*/
// ==========================================
// Vuex Store 状态管理配置详解
// 文件路径: src/store/index.js
// ==========================================/*** 背景知识:* Vuex 是 Vue.js 的状态管理库,用于管理应用的全局状态* 核心概念:State(状态)、Getters(计算属性)、Mutations(同步修改)、Actions(异步操作)* 数据流:组件 → dispatch Action → commit Mutation → 修改 State → 响应式更新组件*/// 1. 导入必要的依赖
import { createStore } from "vuex";  // Vuex 4.x 的创建函数(适配 Vue 3)
import { login, logout } from "@/api/user";  // API 接口函数(与后端通信)/*** 2. 创建 Vuex Store 实例* Store 是一个单一状态树,包含应用的所有状态*/
const store = createStore({/*** 3. State - 状态定义* 存储应用的数据,相当于组件的 data* 初始值从 localStorage 读取,实现持久化存储*/state: {// 用户认证令牌(JWT Token)// 用于后端API请求的身份验证token: localStorage.getItem("token") || "",// 用户信息对象// 包含用户名、ID、头像等基本信息user: JSON.parse(localStorage.getItem("user") || "{}"),// 用户角色// 用于前端权限控制(如:admin、user、guest)role: localStorage.getItem("role") || "",},/*** 4. Getters - 计算属性* 类似组件的 computed,用于派生状态* 可以对 state 进行处理后返回,具有缓存特性*/getters: {// 获取 tokentoken: (state) => state.token,// 获取用户信息user: (state) => state.user,// 获取用户角色role: (state) => state.role,// 判断是否为管理员(派生状态)// 这是一个计算属性,根据 role 动态计算isAdmin: (state) => state.role === "admin",// 可以添加更多 getters,例如:// isLoggedIn: (state) => !!state.token,  // 是否已登录// userName: (state) => state.user.name || '游客',  // 用户名},/*** 5. Mutations - 同步状态修改* 唯一能修改 state 的方法,必须是同步函数* 通过 commit 触发:store.commit('SET_TOKEN', value)* * 命名约定:通常使用大写常量风格*/mutations: {// 设置 tokenSET_TOKEN(state, token) {state.token = token;  // 更新内存中的状态localStorage.setItem("token", token);  // 持久化到本地存储},// 设置用户信息SET_USER(state, user) {state.user = user;// JSON.stringify 将对象序列化为字符串存储localStorage.setItem("user", JSON.stringify(user));},// 设置用户角色SET_ROLE(state, role) {state.role = role;localStorage.setItem("role", role);},// 清除用户信息(用于登出)CLEAR_USER(state) {// 重置所有用户相关状态state.token = "";state.user = {};state.role = "";// 清除本地存储localStorage.removeItem("token");localStorage.removeItem("user");localStorage.removeItem("role");},},/*** 6. Actions - 异步操作* 用于处理异步逻辑(如 API 请求)* 通过 dispatch 触发:store.dispatch('login', payload)* 可以包含任意异步操作,最终通过 commit 调用 mutation*/actions: {/*** 登录操作* @param {Object} context - 包含 commit、dispatch、state 等* @param {Object} loginForm - 登录表单数据(用户名、密码)*/async login({ commit }, loginForm) {try {// 1. 调用登录 APIconst response = await login(loginForm);// 2. 解构响应数据// 假设后端返回格式:{ data: { token, user, role } }const { token, user, role } = response.data;// 3. 通过 mutations 更新状态commit("SET_TOKEN", token);commit("SET_USER", user);commit("SET_ROLE", role);// 4. 返回响应(供组件使用)return response;} catch (error) {// 错误处理console.error('登录失败:', error);// 可以添加更详细的错误处理// 例如:根据错误码显示不同提示if (error.response?.status === 401) {throw new Error('用户名或密码错误');} else if (error.response?.status === 500) {throw new Error('服务器错误,请稍后重试');}// 继续抛出错误,让调用方处理throw error;}},/*** 登出操作* @param {Object} context - Vuex context 对象*/async logout({ commit }) {try {// 1. 调用登出 API(通知后端清除 session 或 token)await logout();} catch (error) {// 即使 API 调用失败,也要清除本地状态console.error("Logout API error:", error);} finally {// 2. 无论成功与否,都清除本地用户信息commit("CLEAR_USER");}},// 可以添加更多 actions,例如:// async updateProfile({ commit }, profileData) { ... }// async refreshToken({ commit }) { ... }},/*** 7. Modules(模块化)- 这里未使用,但是重要概念* 当应用变大时,可以将 store 分割成模块* * modules: {*   user: userModule,*   product: productModule,*   cart: cartModule* }*/
});// 导出 store 实例
export default store;/*** 使用示例:* * 1. 在组件中使用 state:*    computed: {*      token() { return this.$store.state.token }*    }* * 2. 使用 getters:*    computed: {*      isAdmin() { return this.$store.getters.isAdmin }*    }* * 3. 调用 mutations:*    this.$store.commit('SET_TOKEN', 'new-token')* * 4. 调用 actions:*    this.$store.dispatch('login', { username, password })* * 5. 使用辅助函数(更简洁):*    import { mapState, mapGetters, mapActions } from 'vuex'*    computed: {*      ...mapState(['token', 'user']),*      ...mapGetters(['isAdmin'])*    },*    methods: {*      ...mapActions(['login', 'logout'])*    }* * 6. 在路由守卫中使用(如第一个文件所示):*    const token = store.getters.token*//*** 注意事项:* * 1. LocalStorage 的局限性:*    - 存储容量有限(通常 5-10MB)*    - 只能存储字符串*    - 同步操作,可能阻塞主线程*    - 不适合存储敏感信息* * 2. Token 安全性:*    - 考虑使用 httpOnly Cookie 存储 token*    - 实现 token 刷新机制*    - 设置合理的过期时间* * 3. 性能优化:*    - 避免在 state 中存储大量数据*    - 使用 getters 缓存计算结果*    - 合理使用模块化分割 store*/
http://www.dtcms.com/a/340281.html

相关文章:

  • 【Day 31】Linux-LNMP
  • MySQL基础操作
  • SpringBoot + MyBatis-Plus 使用 listObjs 报 ClassCastException 的原因与解决办法
  • Rabbit 实战指南-学习笔记
  • HTML+CSS:浮动详解
  • 3D文档控件Aspose.3D实用教程:使用 C# 构建 OBJ 到 U3D 转换器
  • awk 基础用法示例
  • 测试DuckDB插件对不同格式xlsx文件的读写效率
  • MyCAT分库分表
  • Go特有的安全漏洞及渗透测试利用方法(通俗易懂)
  • 次短路P2865 [USACO06NOV] Roadblocks G题解
  • SLAM文献之-Globally Consistent and Tightly Coupled 3D LiDAR Inertial Mapping
  • RESP协议
  • React响应式链路
  • SCAU学习笔记 - 自科三面前端方向实战演示
  • 157-基于Python的懂车帝汽车数据爬虫分析与可视化系统
  • NVIDIA Isaac Sim
  • Ubuntu 主机名:精通配置与管理
  • 全球首款 8K 全景无人机影翎 A1 发布解读:航拍进入“先飞行后取景”时代
  • 从 “模仿” 到 “创造”:AI 大模型的 “思维进化” 背后,技术突破在哪?
  • 沪深股指期货指数「IF000」期货行情怎么看?
  • 利用无事务方式插入数据库解决并发插入问题(最小主键id思路)
  • 海外短剧app、h5、独立站、国内短剧看广告app,短剧小程序、源码交付开发
  • java17学习笔记
  • RK android14 Setting一级菜单IR遥控器无法聚焦问题解决方法
  • VPS海外节点性能监控全攻略:从基础配置到高级优化
  • 02-docker相关知识
  • Java 学习笔记(基础篇6)
  • 29.Linux rsync+inotify解决同步数据实时性
  • 【Tech Arch】Apache HBase分布式 NoSQL 数据库