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.pswp.cn/news/919589.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/919589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux Capability 解析

文章目录1. 权限模型演进背景2. Capability核心原理2.1 能力单元分类2.2 进程三集合2.3 文件系统属性3. 完整能力单元表4. 高级应用场景4.1 能力边界控制4.2 编程控制4.3 容器安全5. 安全实践建议6. 潜在风险提示 1. 权限模型演进背景 在传统UNIX权限模型中&#xff0c;采用二进…

vue 监听 sessionStorage 值的变化

<template><div class"specific-storage-watcher"><h3>仅监听 userId 变化</h3><p>当前 userId: {{ currentUserId }}</p><p v-if"changeRecord">最近变化: {{ changeRecord }}</p><button click"…

IDEA:控制台中文乱码

目录一、设置字符编码为 UTF-8一、设置字符编码为 UTF-8 点击菜单 File -> settings -> Eitor -> File Encodings , 将字符全局编码、项目编码、配置文件编码统一设置为UTF-8, 然后点击 Apply 应用设置&#xff0c;点击 OK 关闭对话框:

[Sql Server]特殊数值计算

任务一&#xff1a;求下方的Num列的中值:参考代码:use Test go SELECT DISTINCTPERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Num) over()AS MedianSalary FROM MedianTest;任务二: 下方表中,每个选手有多个评委打分&#xff0c;求每个选手的评委打分中值。参考代码:use Tes…

01-Docker概述

Docker 的主要目标是:Build, Ship and Run Any App, Anywhere,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的 APP 及其运行环境能做到一次镜像,处处运行。 Docker 运行速度快的原因: 由于 Docker 不需要 Hypervisor(虚拟机)实现硬件资源虚拟化…

Laravel中如何使用php-casbin

一、&#x1f680; 安装和配置 1. 安装包 composer require casbin/laravel-authz2. 发布配置文件 php artisan vendor:publish这会生成两个重要文件&#xff1a; config/lauthz.php - 主配置文件config/lauthz-rbac-model.conf - RBAC 模型配置文件 3. 运行数据库迁移 php…

算法题打卡力扣第4题:寻找两个正序数组的中位数(hard))

题目描述 提示&#xff1a; nums1.length m nums2.length n 0 < m < 1000 0 < n < 1000 1 < m n < 2000 -106 < nums1[i], nums2[i] < 106 解答思路 我的想法是先归并排序再直接返回下标中位数 代码 double findMedianSortedArrays(int* nums1,…

无人机抗噪模块技术概述!

一、 技术要点1. 传感器数据融合与滤波&#xff08;解决感知噪声&#xff09;核心思想&#xff1a;单一传感器易受干扰且不全面&#xff0c;通过融合多种传感器&#xff08;IMU惯性测量单元、GPS、气压计、磁力计、视觉传感器、激光雷达等&#xff09;的数据&#xff0c;利用算…

Horse3D游戏引擎研发笔记(六):在QtOpenGL环境下,仿Unity的材质管理Shader绘制四边形

在上一篇笔记中&#xff0c;我们已经实现了基于QtOpenGL的BufferGeometry管理VAO和EBO绘制四边形的功能。这一次&#xff0c;我们将深入探讨材质管理系统的实现&#xff0c;包括Shader的加载与编译、材质的创建与使用&#xff0c;以及如何通过材质系统绘制带有自定义Shader效果…

MySQL-分库分表(Mycat)

目录 1.介绍​ 概述 拆分策略 垂直拆分​ 水平拆分​ 实现技术​ shardingJDBC: MyCat: 2.Mycat概述 环境准备​ 分片配置 schema.xml​ server.xml 启动服务​ 分片测试​ 3.MyCat配置 schema.xml​ schema标签 datanode标签 ​datahost标签​ rule.xml …

Dubbo 的 Java 项目间调用的完整示例

1. 项目结构假设项目分为三个模块&#xff1a;api&#xff1a;定义服务接口provider&#xff1a;服务提供者consumer&#xff1a;服务消费者2. 依赖配置在 pom.xml 中添加 Dubbo 和注册中心&#xff08;如 Nacos&#xff09;的依赖&#xff1a;<dependency><groupId&g…

Python进行中文分词

1. jieba库概述 jieba&#xff08;“结巴”&#xff09;是Python中最流行的中文分词库&#xff0c;采用基于前缀词典实现的高效分词算法&#xff0c;支持多种分词模式&#xff0c;是中文自然语言处理(NLP)的基础工具。 核心特性 精确模式&#xff1a;试图将句子最精确地切开&am…

JavaScript 性能优化实战:从原理到落地的完整指南

一、引言&#xff1a;为什么 JavaScript 性能优化至关重要&#xff1f;性能与用户体验的强关联数据支撑&#xff1a;加载延迟每增加 1 秒&#xff0c;用户转化率下降 7%&#xff08;来自 Google 研究&#xff09;核心痛点&#xff1a;现代 Web 应用中 JS 代码体积膨胀、运行时卡…

前端自动化部署

摘要&#xff1a;前端自动化部署是通过工具和流程自动化实现前端代码从开发完成到线上发布的全流程&#xff0c;减少人工操作、提高效率并降低出错风险。核心目标减少重复操作&#xff1a;自动化构建、测试、部署等步骤&#xff0c;替代手动上传服务器等低效方式。提升发布效率…

peewee中db.create_tables(tables, safe=True),safe=True作用

db.create_tables(tables, safeTrue) 中的 safeTrue 参数的作用是 防止在表已经存在的情况下引发错误。 具体来说&#xff1a; 当 safeTrue 时&#xff1a;Peewee 会在生成的 SQL 语句中加入 IF NOT EXISTS 子句&#xff08;例如&#xff1a;CREATE TABLE IF NOT EXISTS my_tab…

2025年计算机视觉与图像国际会议(ICCVI 2025)

2025年计算机视觉与图像国际会议| 视界创新&#xff0c;图领未来 2025年计算机视觉与图像国际会议&#xff08;ICCVI 2025&#xff09;将在中国东莞盛大召开。这不仅是一次汇聚全球顶尖科学家、工程师和学者的盛会&#xff0c;更是一个探索计算机视觉和图像处理领域前沿技术与未…

Temu美国站大规模扫号封店:虚假本土店遭批量封禁,如何规避?

2025年8月&#xff0c;Temu平台针对美国站再次掀起大规模扫号风暴。大量店铺因注册信息违规被判定为“高风险”&#xff0c;不仅店铺被冻结&#xff0c;商品也被下架并禁止补货。这一轮清扫&#xff0c;让不少依靠“资料店”快速起盘的卖家遭遇重创。事实上&#xff0c;Temu的风…

航空发动机叶片yolov8模型训练和转换(包含适配rk3588-pt转onnx转rknn)

前言&#xff1a; 1.训练在windows进行&#xff0c;因为电脑没有显卡&#xff0c;所以纯cpu训练&#xff0c;生成pt后转onnx 2.onnx转需要在Ubuntu虚拟机上运行 3.数据集标定快捷键 &#xff08;模型训练时不需要&#xff09;官方地址和下载pt权重&#xff1a;链接&#xff…

PyTorch如何修改模型(魔改)?/替换模型,一般除了注意输入输出一致,还有其他要修改的吗?

一、PyTorch如何修改模型&#xff08;魔改&#xff09;? 可以参考这个链接&#xff0c;看了一下还不错&#xff1a; PyTorch如何修改模型&#xff08;魔改&#xff09;_模型魔改-CSDN博客 二、替换模型&#xff0c;一般除了注意输入输出一致&#xff0c;还有其他要修改的吗?…

Pycharm Debug详解

Pycharm Debug详解看这个工具栏就是 PyCharm 调试器的“步进/断点”按钮区。常用按钮和作用&#xff08;从左到右一般是这些&#xff09;&#xff1a; Resume / 继续运行&#xff08;F9&#xff09;&#xff1a;从当前断点继续跑&#xff0c;直到下一个断点或程序结束。Step Ov…