在 Vue 前端项目中实现自动存储 Mock 数据,并在无网络环境下切换到 Mock 数据,可以提升应用的可靠性和用户体验。以下是一个综合的解决方案,结合 Axios 拦截器 和 本地存储(如 IndexedDB),实现自动捕获和存储 API 响应,并在网络不可用时使用存储的 Mock 数据。
解决方案概述
使用 Axios 拦截器:
- 响应拦截器:在正常网络情况下,拦截 API 响应并将数据存储到本地。
- 请求拦截器:在检测到网络不可用时,从本地存储中获取对应的 Mock 数据,返回给前端。
本地存储选择:
网络状态检测:
- 使用浏览器的
navigator.onLine
属性和 window
事件监听器来检测网络状态变化。
数据同步(可选):
- 在网络恢复后,可以选择性地同步本地存储的数据与后端。
详细实现步骤
1. 安装必要的依赖
首先,安装 Axios 和 localForage:
npm install axios localforage
|
2. 配置 LocalForage
创建一个 storage.js
文件,用于配置和导出 LocalForage 实例:
import localforage from 'localforage'
localforage.config({ name: 'vue-app', storeName: 'api_responses', description: 'Store API responses for offline use' })
export default localforage
|
3. 设置 Axios 拦截器
在项目中创建一个 axios.js
文件,配置 Axios 实例及其拦截器:
import axios from 'axios' import storage from './storage'
const apiClient = axios.create({ baseURL: '/api', timeout: 10000, })
apiClient.interceptors.request.use(async (config) => { if (!navigator.onLine) { const key = generateCacheKey(config) const cachedResponse = await storage.getItem(key) if (cachedResponse) { config.adapter = () => { return Promise.resolve({ data: cachedResponse.data, status: cachedResponse.status, statusText: 'OK', headers: cachedResponse.headers, config, request: {}, }) } } } return config }, (error) => { return Promise.reject(error) })
apiClient.interceptors.response.use(async (response) => { if (navigator.onLine) { const key = generateCacheKey(response.config) const dataToStore = { data: response.data, status: response.status, headers: response.headers, timestamp: Date.now(), } await storage.setItem(key, dataToStore) } return response }, (error) => { return Promise.reject(error) })
function generateCacheKey(config) { return `${config.method.toUpperCase()}_${config.url}_${JSON.stringify(config.params || {})}_${JSON.stringify(config.data || {})}` }
export default apiClient
|
说明:
请求拦截器:在每次请求前检查网络状态。如果网络不可用,尝试从本地存储中获取对应的响应数据,并通过自定义适配器返回该数据,避免实际发起网络请求。
响应拦截器:在网络可用时,拦截所有成功的响应,并将响应数据存储到本地,以备后续离线使用。
缓存键生成:确保每个 API 请求对应一个唯一的缓存键,通常基于请求的 URL、方法、参数和数据。
4. 在 Vue 项目中使用 Axios 实例
在 main.js
中引入并配置 Axios 实例:
import { createApp } from 'vue' import App from './App.vue' import apiClient from './utils/axios'
const app = createApp(App) app.config.globalProperties.$api = apiClient
app.mount('#app')
|
在组件中使用 Axios:
<template> <div> <button @click="fetchUser">获取用户信息</button> <div v-if="user"> <p>ID: {{ user.id }}</p> <p>姓名: {{ user.name }}</p> </div> </div> </template>
<script> export default { data() { return { user: null, } }, methods: { async fetchUser() { try { const response = await this.$api.get('/user') this.user = response.data } catch (error) { console.error('获取用户信息失败:', error) } } } } </script>
|
5. 处理网络状态变化(可选)
为了提升用户体验,可以监听网络状态的变化,并在 UI 上给予提示:
import { reactive } from 'vue'
const state = reactive({ online: navigator.onLine })
window.addEventListener('online', () => { state.online = true })
window.addEventListener('offline', () => { state.online = false })
export default state
|
在组件中使用:
<template> <div> <div v-if="!network.online" class="offline-banner"> 当前处于离线状态,部分功能可能无法使用。 </div> <!-- 其他内容 --> </div> </template>
<script> import network from '@/utils/network'
export default { setup() { return { network } } } </script>
<style> .offline-banner { background-color: #ffcc00; padding: 10px; text-align: center; } </style>
|
6. 缓存失效与数据同步(高级)
为了避免长期使用过时的 Mock 数据,可以设置缓存的失效时间。例如,设置每条缓存数据的有效期为 7 天:
修改 axios.js
中的响应拦截器:
const dataToStore = { data: response.data, status: response.status, headers: response.headers, timestamp: Date.now(), }
if (cachedResponse) { const cacheDuration = 7 * 24 * 60 * 60 * 1000 if (Date.now() - cachedResponse.timestamp < cacheDuration) { config.adapter = () => { return Promise.resolve({ data: cachedResponse.data, status: cachedResponse.status, statusText: 'OK', headers: cachedResponse.headers, config, request: {}, }) } } else { storage.removeItem(key) } }
|
数据同步:
在网络恢复后,可以选择自动同步本地数据与后端,或提示用户手动刷新数据。实现方式视具体需求而定。
备选方案:使用 Service Worker 和 Cache API
如果项目已经使用了 Service Worker(如通过 Vue CLI PWA 插件),可以进一步利用 Service Worker 的拦截和缓存能力,实现更复杂的离线支持。
步骤概述:
- 注册 Service Worker。
- 在 Service Worker 中拦截 API 请求。
- 实现网络优先或缓存优先策略。
- 存储 API 响应到 Cache Storage。
优点:
- 更底层的拦截和缓存机制。
- 支持离线应用的更多功能(如离线页面、资源缓存等)。
缺点:
- 实现复杂度较高。
- 需要更深入的 Service Worker 知识。
推荐工具:
- Workbox:Google 提供的强大工具库,用于简化 Service Worker 的开发。
总结
通过结合 Axios 拦截器 和 本地存储(如 IndexedDB via localForage),可以实现以下功能:
- 自动捕获和存储:在正常网络环境下,自动拦截并存储所有 API 响应数据。
- 离线访问:在网络不可用时,自动从本地存储中提取相应的 Mock 数据,确保应用的基本功能不受影响。
- 缓存管理:通过设置缓存的有效期和同步策略,确保数据的时效性和一致性。
这种方法无需引入额外的 Mock 服务或工具,直接在前端实现,适合需要动态生成和更新 Mock 数据的场景。同时,结合 Vue 的响应式特性和用户界面提示,可以为用户提供流畅的离线体验。
希望这个解决方案能满足你的需求,提升 Vue 前端项目在不同网络环境下的表现!