vue3 路由刷新无感刷新
时间: 2025-04-09 08:27:56 浏览: 28
<think>好的,我现在需要解决用户在Vue3项目中实现路由刷新时无感更新的问题。用户提到的无感刷新通常涉及在Token过期时自动刷新,而用户不会察觉到这个过程。根据用户提供的引用内容,特别是引用[1]到[4],我需要结合这些信息来构建解决方案。
首先,我需要理解双Token机制。双Token通常指的是access_token和refresh_token。access_token用于常规请求,有效期较短;refresh_token用于获取新的access_token,有效期较长。当access_token过期时,前端使用refresh_token请求新的access_token,而用户无需重新登录。
接下来,用户的问题是关于路由刷新时的无感更新。这可能涉及到当页面刷新或路由变化时,如何保持Token的有效性。根据引用[3],无感刷新需要在Token失效时拦截请求,发送刷新Token的请求,然后重试原来的请求。在Vue3中,这通常通过Axios拦截器实现。
然后,我需要考虑如何封装Axios来实现拦截器。引用[1]提到使用Axios的封装方式,在请求拦截器中添加Token,在响应拦截器中处理Token过期的情况。当检测到Token过期(比如401状态码),使用refresh_token调用刷新接口,获取新的access_token,然后重新发送原来的请求。
同时,引用[4]指出需要将两个Token存储在前端缓存中,比如localStorage或vuex/pinia。这样在页面刷新时,可以重新获取Token,保持登录状态。但页面刷新会导致Vue应用重新初始化,可能需要从存储中读取Token并更新应用状态。
另外,路由刷新可能涉及到Vue Router的导航守卫。在路由跳转前检查Token的有效性,如果Token已过期,可能需要先刷新Token再允许导航。但用户希望无感,所以应该在后台处理,而不是中断用户操作。
还需要处理多个并发请求的情况。当多个请求同时发现Token过期时,应该只发送一次刷新Token的请求,其他请求等待刷新完成后再用新Token重试。这可以通过一个Promise队列来实现,避免重复刷新。
此外,错误处理也很重要。如果refresh_token也过期了,就需要跳转到登录页面,让用户重新登录。此时需要清除旧的Token,并提示用户。
最后,结合引用[2]提到的无感刷新机制,整个流程需要确保用户无感知,即在后台静默处理Token刷新,不影响当前操作。
总结步骤:封装Axios拦截器处理Token刷新,使用存储保持Token持久化,处理并发请求的Token刷新,结合路由守卫进行必要的验证,处理可能的错误情况。这样就能在路由刷新时实现无感更新,保持用户登录状态。</think>### Vue3路由刷新实现无感刷新的解决方案
在Vue3项目中实现路由刷新的无感更新,核心在于**双Token机制**与**Axios拦截器封装**的结合。以下是具体实现步骤和最佳实践:
---
#### 一、双Token存储与初始化
1. **登录时存储双Token**
- 用户登录成功后,将返回的`access_token`(短期有效)和`refresh_token`(长期有效)存入`localStorage`或`Pinia/Vuex`中[^4]:
```javascript
localStorage.setItem('access_token', accessToken);
localStorage.setItem('refresh_token', refreshToken);
```
2. **初始化时加载Token**
- 在应用启动时(如`main.ts`)从存储中读取Token,避免路由刷新后丢失:
```javascript
const accessToken = localStorage.getItem('access_token');
const refreshToken = localStorage.getItem('refresh_token');
```
---
#### 二、Axios拦截器封装
1. **请求拦截器:自动添加Token**
- 每次请求前将`access_token`添加到请求头:
```javascript
axios.interceptors.request.use(config => {
const token = localStorage.getItem('access_token');
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
```
2. **响应拦截器:处理Token过期**
- 当接口返回`401`状态码时,触发Token刷新逻辑:
```javascript
axios.interceptors.response.use(
response => response,
async error => {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// 调用刷新Token接口
const newToken = await refreshToken();
localStorage.setItem('access_token', newToken);
// 重试原始请求
return axios(originalRequest);
}
return Promise.reject(error);
}
);
```
---
#### 三、Token刷新逻辑
1. **静默刷新Token**
- 使用`refresh_token`调用专用接口获取新`access_token`,避免用户感知[^2]:
```javascript
const refreshToken = async () => {
const refreshToken = localStorage.getItem('refresh_token');
const { data } = await axios.post('/auth/refresh', { refreshToken });
return data.access_token;
};
```
2. **处理并发请求**
- 使用队列机制保证多个并发请求过期时,仅触发一次Token刷新:
```javascript
let isRefreshing = false;
let failedQueue = [];
// 在拦截器中添加队列处理
if (!isRefreshing) {
isRefreshing = true;
refreshToken().then(newToken => {
localStorage.setItem('access_token', newToken);
failedQueue.forEach(cb => cb(newToken));
failedQueue = [];
});
}
return new Promise(resolve => {
failedQueue.push(token => {
originalRequest.headers.Authorization = `Bearer ${token}`;
resolve(axios(originalRequest));
});
});
```
---
#### 四、路由守卫处理
在`vue-router`中配置全局前置守卫,确保路由跳转时Token有效:
```javascript
router.beforeEach(async (to) => {
const accessToken = localStorage.getItem('access_token');
if (to.meta.requiresAuth && !accessToken) {
return '/login';
}
// 可选:检查Token有效期,若临近过期则提前刷新
});
```
---
#### 五、错误边界处理
1. **刷新Token失败**
- 当`refresh_token`过期时,跳转登录页并清除缓存:
```javascript
try {
await refreshToken();
} catch (error) {
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
router.push('/login');
}
```
---
###
阅读全文