程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 后端开发

  • 前端开发

    • 照片上传组件
    • localStorage工具类
    • sessionStorage工具类
    • 对话框组件
    • 消息提示工具类
    • 按钮组件
    • 前端文件上传
    • 前端文件下载
    • 前端数据一致性
      • 1. 理论背景
        • 1.1 为什么需要使用 Vuex 和本地存储?
        • 1.2 localStorage vs sessionStorage
      • 2. 实现步骤
        • 2.1 用户信息存储在 localStorage 的方案
        • 2.2 支持 localStorage 和 sessionStorage 的方案
        • 2.3 用户登录成功之后同步信息到vuex
        • 2.4 如何在 Vuex 中处理用户信息的部分更新
        • 2.5 vuex完整代码
        • 2.6 前端请求响应拦截器
      • 3. 总结与补充说明
    • 后台管理系统组件
  • 开发笔记
  • 前端开发
scholar
2024-12-27
目录

前端数据一致性

# 前端用户登录后如何保持数据一致性

在前端开发中,用户登录后,用户信息的管理是一个非常重要的环节。我们需要确保用户信息在整个应用中保持一致,并且在页面刷新后不丢失。这通常涉及到以下几个步骤:

  1. 用户信息的存储:在用户登录成功后,我们需要将用户信息存储在浏览器的 localStorage 或 sessionStorage 中。
  2. Vuex 中的状态管理:为了方便在应用的不同组件之间共享用户信息,我们通常会使用 Vuex 来管理这些信息。
  3. 数据的同步与持久化:为了避免页面刷新导致 Vuex 中的数据丢失,我们需要在 Vuex 初始化时从 localStorage 或 sessionStorage 中加载用户信息,并在用户信息更新时同步到本地存储中。

# 1. 理论背景

# 1.1 为什么需要使用 Vuex 和本地存储?

  • 数据共享:在大型应用中,用户信息可能会被多个组件使用。通过 Vuex,我们可以轻松实现数据的共享,并确保数据的一致性。
  • 数据持久化:Vuex 中的数据是保存在内存中的,这意味着一旦页面刷新,数据将会丢失。因此,我们需要将重要的数据(如用户信息)存储在 localStorage 或 sessionStorage 中,以便在页面刷新时重新加载这些数据。

# 1.2 localStorage vs sessionStorage

  • localStorage:数据会一直保存在浏览器中,直到用户手动删除或清除缓存。适用于需要长期保存的数据。
  • sessionStorage:数据只在当前会话中有效,关闭浏览器窗口后数据会被清除。适用于需要临时保存的数据。

# 2. 实现步骤

  1. 用户登录成功后:我们首先将用户信息提交到 Vuex 中,这样可以方便在应用的不同组件之间共享这些信息。
  2. Vuex 中的数据同步到本地存储:在用户信息提交到 Vuex 后,我们会自动将这些信息同步到本地浏览器的存储(localStorage 或 sessionStorage)中。

# 2.1 用户信息存储在 localStorage 的方案

在这个方案中,用户信息在登录成功后会被存储到 Vuex 中。我们会将这些信息同步到 localStorage,并在用户信息变更时同时更新 localStorage。

代码实现:

  1. 创建 Vuex Store

    首先,我们创建一个 Vuex Store,用于管理应用中的用户信息和其他状态数据。

    // 引入 Vue 核心库
    import Vue from 'vue';
    // 引入 Vuex
    import Vuex from 'vuex';
    
    // 应用 Vuex 插件
    Vue.use(Vuex);
    
    // 同步用户信息到 localStorage 的辅助函数
    function syncUserToLocalStorage(user) {
      // 将用户信息序列化后存储到 localStorage 中
      localStorage.setItem('xm-user', JSON.stringify(user));
    }
    
    // 准备 state 对象——保存具体的数据
    const state = {
      activeIndex: '/home', // 当前激活的菜单索引
      user: {
        id: '', // 用户ID
        username: '', // 用户名
        avatar: '', // 用户头像
        email: '', // 用户邮箱
        token: '', // 用户令牌
        callbackUrl: '' // 回调地址
      }
    };
    
    // 准备 mutations 对象——修改 state 中的数据
    const mutations = {
      EditActiveIndex(state, val) {
        state.activeIndex = val; // 修改激活的菜单索引
      },
      EditUser(state, val) {
        state.user = { ...state.user, ...val };  // 合并更新用户信息,保留未修改的数据
        syncUserToLocalStorage(state.user); // 同步用户信息到 localStorage
      }
    };
    
    // 创建并导出 store
    const store = new Vuex.Store({
      state,
      mutations
    });
    
    // 在应用初始化时,从 localStorage 加载用户信息到 Vuex
    const savedUser = JSON.parse(localStorage.getItem('xm-user') || '{}');
    
    // 检查存储数据的完整性,避免无效数据覆盖 Vuex 状态
    if (savedUser.id) { // 判断 id 是否存在,确保数据有效
      store.commit('EditUser', savedUser); // 将保存的用户信息同步到 Vuex
    }
    
    export default store;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53

    代码详解:

    • syncUserToLocalStorage 函数:用于将用户信息同步到 localStorage 中。每次用户信息发生变动时,都会调用这个函数。
    • state 对象:state 中保存了当前的用户信息和菜单索引等数据。
    • mutations 对象:mutations 用于修改 state 中的数据,并在用户信息修改后同步到 localStorage。
    • 应用初始化:在应用初始化时,我们从 localStorage 中加载用户信息到 Vuex,确保刷新页面后数据不丢失。
  2. 用户登录后的处理

    当用户登录成功后,我们需要将用户信息存储到 Vuex 并同步到 localStorage。

    methods: {
      handleLogin() {
        this.$refs.loginForm.validate((valid) => {
          if (valid) {
            request.post('/web/login', this.loginForm)
              .then(response => {
                if(response && response.code === 200) {
                  this.$message.success('登录成功');
                  const user = response.data;
                  
                  // 将用户信息同步到 Vuex 和 localStorage
                  this.$store.commit("EditUser", user);
                  
                  this.$router.push('/main'); // 登录成功后跳转到主页面
                } else {
                  this.$message.error(response.message);
                }
              });
          }
        });
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    代码详解:

    • handleLogin 方法:在用户登录成功后,调用 EditUser mutation 更新 Vuex 中的用户信息,同时会自动同步到 localStorage 中。

# 2.2 支持 localStorage 和 sessionStorage 的方案

在某些情况下,我们可能需要根据用户选择的“记住我”选项,动态选择将用户信息存储到 localStorage 或 sessionStorage 中。为此,我们扩展了之前的方案,支持在登录时动态选择存储方式。

代码实现:

  1. 创建 Vuex Store

    在这个方案中,我们在 Vuex 的 state 中新增一个 storageType 字段,用于记录当前用户信息存储在哪个存储中。

    // 引入 Vue 核心库
    import Vue from 'vue';
    // 引入 Vuex
    import Vuex from 'vuex';
    
    // 应用 Vuex 插件
    Vue.use(Vuex);
    
    // 同步用户信息到存储的辅助函数
    function syncUserToStorage(user, storageType) {
      const storage = storageType === 'local' ? localStorage : sessionStorage;
      storage.setItem('xm-user', JSON.stringify(user));
    }
    
    // 准备 state 对象——保存具体的数据
    const state = {
      activeIndex: '/home', // 当前激活的菜单索引
      user: {
        id: '', // 用户ID
        username: '', // 用户名
        avatar: '', // 用户头像
        email: '', // 用户邮箱
        token: '', // 用户令牌
        callbackUrl: '' // 回调地址
      },
      storageType: 'local' // 默认使用 localStorage
    };
    
    // 准备 mutations 对象——修改 state 中的数据
    const mutations = {
      EditActiveIndex(state, val) {
        state.activeIndex = val; // 修改激活的菜单索引
      },
      EditUser(state, val) {
        state.user = { ...state.user, ...val };  // 合并更新用户信息,保留未修改的数据
        // 根据 storageType 来确定修改后的用户信息同步到local还是session
        syncUserToStorage(state.user, state.storageType);
      },
      SetStorageType(state, storageType) {
        state.storageType = storageType; // 设置存储类型为 localStorage 或 sessionStorage
      }
    };
    
    // 创建并导出 store
    const store = new Vuex.Store({
      state,
      mutations
    });
    
    // 刷新页面的时候,vuex数据丢失,我们会按以下步骤重新加载数据
    // 首先从 localStorage 获取中的用户信息,并设置存储类型为local
    let savedUser = JSON.parse(localStorage.getItem('xm-user') || '{}');
    let storageType = 'local';
    
    // 如果localStorage中没有获取到,我们再从sessionStorage中获取,并设置存储类型为session
    if (Object.keys(savedUser).length === 0) {
      savedUser = JSON.parse(sessionStorage.getItem('xm-user') || '{}');
      storageType = 'session';
    }
    
    // 如果用户信息存在,更新 Vuex 的状态
    if (Object.keys(savedUser).length > 0) {
      store.commit('SetStorageType', storageType);
      store.commit('EditUser', savedUser);
    }
    
    export default store;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67

    代码详解:

    • syncUserToStorage 函数:根据传入的 storageType 参数决定将用户信息保存到 localStorage 还是 sessionStorage 中。

    • storageType:用于记录当前用户信息保存在哪种存储中,以确保后续的同步操作能正确进行。

    • 初始化逻辑:首先尝试从 localStorage 获取用户信息,如果获取不到,再从 sessionStorage 获取,并根据获取到的信息来源设置 storageType。

  2. 用户登录后的处理

    登录时,根据用户是否选择“记住我”来决定用户信息保存的位置。

    methods: {
      handleLogin() {
        this.$refs.loginForm.validate((valid) => {
          if (valid) {
            request.post('/web/login', this.loginForm)
              .then(response => {
                if(response && response.code === 200) {
                  this.$message.success('登录成功');
                  const user = response.data;
                  
                  if (this.loginForm.rememberMe) {
                    this.$store.commit("SetStorageType", 'local');
                    this.$store.commit("EditUser", user);
                  } else {
                    this.$store.commit("SetStorageType", 'session');
                    this.$store.commit("EditUser", user);
                  }
                  
                  this.$router.push('/main'); // 登录成功后跳转到主页面
                } else {
                  this.$message.error(response.message);
                }
              });
          }
        });
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    代码详解:

    • handleLogin 方法:在用户登录成功后,根据“记住我”选项设置 storageType,然后更新 Vuex 和对应的存储(localStorage 或 sessionStorage)。

# 2.3 用户登录成功之后同步信息到vuex

  1. 发送登录请求:用户提交登录表单,前端通过 request(或其他 HTTP 库)将表单数据发送给后端服务器进行验证。

  2. 接收服务器响应:服务器验证成功后,会返回完整的用户信息(包括 id、username、email 等)。

  3. 将用户信息提交到 Vuex:

    • 使用 Vuex 的 commit 方法将完整的用户信息提交到 Vuex 中的 user 状态。
    • 同时,Vuex 会自动将用户信息同步到本地存储(localStorage 或 sessionStorage)。
methods: {
  handleLogin() {
    // 进行表单验证
    this.$refs.loginForm.validate((valid) => {
      if (valid) {
        // 向服务器发送登录请求
        request.post('/web/login', this.loginForm)
          .then(response => {
            if (response && response.code === 200) {
              this.$message.success('登录成功');
              
              const user = response.data;  // 服务器返回的完整用户信息

              // 根据用户是否选择“记住我”,确定存储类型
              const storageType = this.loginForm.rememberMe ? 'local' : 'session';

              // 将存储类型设置到 Vuex
              this.$store.commit('SetStorageType', storageType);

              // 将用户信息提交到 Vuex,并同步到指定的存储(localStorage 或 sessionStorage)
              this.$store.commit('EditUser', user);
              
              // 登录成功后跳转到主页面
              this.$router.push('/main');
            } else {
              this.$message.error(response.message);
            }
          })
          .catch(error => {
            console.error('登录失败:', error);
            this.$message.error('登录失败,请检查您的网络连接或联系管理员。');
          });
      }
    });
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

存储类型选择:

  • 使用 this.loginForm.rememberMe 来决定用户信息存储在 localStorage 还是 sessionStorage 中。如果用户选择了“记住我”,则使用 localStorage,否则使用 sessionStorage。

更新 Vuex 和存储:

  • SetStorageType:先通过 SetStorageType mutation 将当前的存储类型(localStorage 或 sessionStorage)保存到 Vuex 中的 storageType 字段。
  • EditUser:然后通过 EditUser mutation 将服务器返回的用户信息合并更新到 Vuex 的 user 状态中,并自动同步到相应的存储。

# 2.4 如何在 Vuex 中处理用户信息的部分更新

  1. 合并更新:
    • EditUser mutation 使用 state.user = { ...state.user, ...val } 来更新用户信息。这意味着当你传入部分用户信息时,只会更新指定的字段,未传入的字段会保留原来的值。
    • 例如,如果只传入 { email: 'newemail@example.com' },那么 state.user 的其他字段如 username、avatar 等将保持不变。
  2. 确保同步:
    • 每次更新用户信息后,都会调用 syncUserToStorage 函数,将最新的用户信息同步到 localStorage 或 sessionStorage 中。这保证了即使刷新页面,Vuex 也能从存储中恢复最新的用户信息。

假设用户在表单中更新了他们的邮箱地址,并提交表单。我们可以这样处理:

methods: {
  updateUserInfo() {
    const updatedUserInfo = {
      email: this.form.email, // 假设用户只修改了邮箱地址
      // 其他可能更新的字段可以在此处添加
    };

    // 提交更新的用户信息到 Vuex
    this.$store.commit('EditUser', updatedUserInfo);

    // 提交后可能进行一些后续操作,例如显示成功提示
    this.$message.success('用户信息已更新');
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在这个例子中,即使用户只修改了邮箱地址,Vuex 也能正确地更新用户信息,同时保留其他未修改的字段。

小结

以上方案可以兼容用户只修改部分字段或全部字段的情况。通过使用对象合并({ ...state.user, ...val }),我们可以确保 Vuex 中的用户信息始终是完整和最新的。同时,每次更新后,我们都会同步信息到本地存储,确保页面刷新后数据不丢失。这种设计能够在不影响用户体验的前提下,保持数据的一致性和持久性。

# 2.5 vuex完整代码

// 引入 Vuex
import { createStore } from 'vuex';

// 同步用户信息到存储的辅助函数
function syncUserToStorage(user, storageType) {
  const storage = storageType === 'local' ? localStorage : sessionStorage;
  storage.setItem('xm-user', JSON.stringify(user));
}

// 准备 state 对象——保存具体的数据
const state = {
  activeIndex: '/home', // 当前激活的菜单索引
  tabList: [{ name: "首页", path: "/main/home" }], // 保存当前打开的标签页列表
  user: {
    // 你之前的用户信息相关字段在这里
  },
  storageType: 'local', // 默认使用 localStorage
  collapse: false // 控制导航栏的折叠状态
};

// 准备 mutations 对象——修改 state 中的数据
const mutations = {
  EditActiveIndex(state, val) {
    state.activeIndex = val; // 修改激活的菜单索引
  },
  EditUser(state, val) {
    state.user = { ...state.user, ...val };  // 合并更新用户信息,保留未修改的数据
    // 根据 storageType 来确定修改后的用户信息同步到local还是session
    syncUserToStorage(state.user, state.storageType);
  },
  SetStorageType(state, storageType) {
    state.storageType = storageType; // 设置存储类型为 localStorage 或 sessionStorage
  },
  saveTab(state, tab) {
    // 如果当前标签页不在 tabList 中,则添加到 tabList
    if (!state.tabList.find(item => item.path === tab.path)) {
      state.tabList.push({ name: tab.meta.name, path: tab.path });
    }
  },
  removeTab(state, tab) {
    // 根据标签名找到对应的索引并删除
    const index = state.tabList.findIndex(item => item.path === tab.path);
    state.tabList.splice(index, 1);
  },
  resetTab(state) {
    // 重置标签页,只保留首页
    state.tabList = [{ name: "首页", path: "/main/home" }];
  },
  trigger(state) {
    // 切换导航栏的折叠状态
    state.collapse = !state.collapse;
  }
};

// 创建并导出 store
const store = createStore({
  state,
  mutations
});

// 刷新页面的时候,vuex数据丢失,我们会按以下步骤重新加载数据
// 首先从 localStorage 获取中的用户信息,并设置存储类型为local
let savedUser = JSON.parse(localStorage.getItem('xm-user') || '{}');
let storageType = 'local';

// 如果localStorage中没有获取到,我们再从sessionStorage中获取,并设置存储类型为session
if (Object.keys(savedUser).length === 0) {
  savedUser = JSON.parse(sessionStorage.getItem('xm-user') || '{}');
  storageType = 'session';
}

// 如果用户信息存在,更新 Vuex 的状态
if (Object.keys(savedUser).length > 0) {
  store.commit('SetStorageType', storageType);
  store.commit('EditUser', savedUser);
}

export default store;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

# 2.6 前端请求响应拦截器

import axios from 'axios';
import router from "@/router";
import { Message } from 'element-ui'; // 引入 Element UI 的 Message 模块

// 创建一个新的 axios 实例
const request = axios.create({
  baseURL: '/api',   // 设置基础URL,所有请求会自动加上这个前缀
  timeout: 30000     // 设置请求超时时间为30秒
});

// request 拦截器
// 这个拦截器在每个请求发送前都会执行
request.interceptors.request.use(config => {
  config.headers['Content-Type'] = 'application/json;charset=utf-8'; // 设置请求头的内容类型为 JSON

  // 首先尝试从 localStorage 获取用户信息
  let user = JSON.parse(localStorage.getItem("xm-user") || '{}');

  // 如果 localStorage 中没有用户信息,再尝试从 sessionStorage 获取
  if (Object.keys(user).length === 0) {
      user = JSON.parse(sessionStorage.getItem("xm-user") || '{}');
  }

  // 如果用户信息存在,并且 token 存在,将其加入请求头的 Authorization 中
  if (user != null && user.token) {
      config.headers['token'] = `Bearer ${user.token}`;  // 将 token 以 "Bearer " 前缀形式添加到请求头中
  }

  return config;  // 返回修改后的请求配置
}, error => {
  console.error('request error: ' + error); // 如果请求配置出错,打印错误信息
  return Promise.reject(error);  // 返回拒绝的 Promise,阻止请求发送
});

// response 拦截器
// 这个拦截器在每个响应返回后都会执行
request.interceptors.response.use(
    response => {
        let res = response.data;  // 获取响应数据

        console.log(response.data);

        // 如果服务器返回的是字符串数据,尝试将其解析为 JSON 对象
        if (typeof res === 'string') {
            try {
                res = JSON.parse(res);  // 安全解析为 JSON 对象
            } catch (error) {
                console.error('JSON 解析错误:', error);
                Message.error('响应数据格式错误');  // 添加错误提示
                return Promise.reject(new Error('响应数据格式错误')); // 如果解析失败,返回拒绝的 Promise
            }
        }

        // 如果服务器返回 401 错误,表示用户未授权或登录已过期
        if (res.code === 401 || res.code === '401') {  // 检查响应状态码是否为 401(未授权)
            Message.error('登录已过期,请重新登录');  // 添加未授权提示
            router.push('/login');  // 重定向到登录页面
        }
        return res;  // 返回处理后的响应数据
    },
    error => {
        // 检查 error.response 是否存在
        if (error.response) {
            const status = error.response.status;
            if (status === 401) {
                Message.error('登录已过期,请重新登录');  // 添加未授权提示
                router.push('/login');  // 如果是 401 错误,跳转到登录页面
            } else if (status === 403) {
                Message.error('权限不足,访问被拒绝');  // 添加 403 错误提示
            } else if (status === 404) {
                Message.error('请求资源未找到');  // 添加 404 错误提示
            } else {
                // 处理其他状态码错误,比如 500 等
                Message.error(`请求错误,状态码: ${status}`);  // 添加其他错误提示
                console.error(`HTTP 错误: ${status}`);
            }
        } else {
            // 处理网络错误或其他无法预料的错误
            Message.error('网络错误或未知错误,请稍后重试');  // 添加网络错误提示
            console.error('网络错误或未知错误:', error);
        }
        return Promise.reject(error);  // 返回拒绝的 Promise
    }
);

export default request;  // 导出 axios 实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

关键点说明

  1. 创建 Axios 实例:

    • 通过 axios.create() 创建一个具有基础 URL 和超时时间设置的实例,以便所有的请求都遵循相同的配置。
  2. 请求拦截器 (request.interceptors.request.use):

    • 在请求发送前统一设置请求头的 Content-Type 为 application/json。
    • 从 localStorage 或 sessionStorage 中读取用户信息。如果用户已登录,并且有 token,则将 token 添加到请求头的 Authorization 中。
  3. 响应拦截器 (request.interceptors.response.use):

    • 在接收到响应后首先检查返回的数据是否为字符串,如果是字符串则尝试将其解析为 JSON。
    • 处理可能的 401 未授权错误,并提示用户重新登录。
    • 处理其他常见的 HTTP 状态码错误,如 403、404 和服务器错误(如 500)。
    • 如果发生网络错误或未知错误,则给出相应的提示,并将错误信息打印到控制台。
  4. 导出 Axios 实例:

    • 最后,将配置好的 request 实例导出,以便在应用的其他部分使用。

# 3. 总结与补充说明

  1. Vuex 与存储的结合:通过结合 Vuex 和 localStorage 或 sessionStorage,我们可以确保应用中的用户信息在页面刷新后不会丢失,并且能够在不同的组件之间共享这些信息。

  2. 双向同步:通过在 mutations 中处理数据的同时更新存储,我们确保了每次数据变动后,存储中的数据都能及时同步,从而保持数据一致性。

  3. 安全性考虑:在实际生产环境中,敏感信息(如 token)不建议直接存储在 localStorage 或 sessionStorage 中,建议通过更安全的方式(如 HttpOnly 的 Cookie)来管理这些数据。

编辑此页 (opens new window)
上次更新: 2025/03/16, 22:19:39
前端文件下载
后台管理系统组件

← 前端文件下载 后台管理系统组件→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式