持久化存储方案
本地存储方案
Vue.js 应用中常用的本地持久化存储方案包括 localStorage 和 sessionStorage。这两种方案都基于 Web Storage API,提供简单的键值对存储机制。
// 存储数据
localStorage.setItem('userToken', 'abc123def456')
sessionStorage.setItem('currentTab', 'profile')
// 获取数据
const token = localStorage.getItem('userToken')
const activeTab = sessionStorage.getItem('currentTab')
// 删除数据
localStorage.removeItem('userToken')
sessionStorage.clear()
localStorage 的特点是:
- 存储容量约5MB
- 数据永久保存,除非手动清除
- 同源策略限制
- 同步操作可能阻塞主线程
sessionStorage 与 localStorage 的主要区别在于:
- 数据仅在当前会话有效
- 标签页关闭后自动清除
- 不同标签页间隔离
IndexedDB 方案
对于需要存储大量结构化数据的场景,IndexedDB 提供了更强大的解决方案:
// 打开或创建数据库
const request = indexedDB.open('MyDatabase', 1)
request.onupgradeneeded = (event) => {
const db = event.target.result
const store = db.createObjectStore('products', { keyPath: 'id' })
store.createIndex('priceIdx', 'price', { unique: false })
}
request.onsuccess = (event) => {
const db = event.target.result
const transaction = db.transaction('products', 'readwrite')
const store = transaction.objectStore('products')
// 添加数据
store.add({ id: 1, name: 'Laptop', price: 999 })
// 查询数据
const getRequest = store.get(1)
getRequest.onsuccess = () => {
console.log(getRequest.result)
}
}
IndexedDB 的优势包括:
- 支持事务操作
- 支持索引查询
- 存储容量远大于 localStorage
- 异步操作不阻塞UI
- 支持二进制数据存储
Vuex 持久化插件
在 Vuex 状态管理中,可以使用 vuex-persistedstate 插件实现状态持久化:
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
// ...
plugins: [
createPersistedState({
key: 'my-vuex-store',
storage: window.localStorage,
reducer: (state) => ({
user: state.user,
settings: state.settings
}),
paths: ['user.authToken']
})
]
})
配置选项说明:
key
: 存储使用的键名storage
: 指定存储介质(localStorage/sessionStorage)reducer
: 自定义需要持久化的状态paths
: 指定需要持久化的模块路径
Cookie 存储方案
虽然现代前端较少直接操作 Cookie,但在某些场景下仍然有用:
// 设置Cookie
document.cookie = `username=john; expires=${new Date(Date.now() + 86400000).toUTCString()}; path=/`
// 读取Cookie
function getCookie(name) {
const value = `; ${document.cookie}`
const parts = value.split(`; ${name}=`)
if (parts.length === 2) return parts.pop().split(';').shift()
}
Cookie 的特点:
- 每个域名下最多存储50个
- 单个Cookie不超过4KB
- 每次HTTP请求都会携带
- 支持设置过期时间
- 有同源策略限制
文件系统访问API
现代浏览器提供了 File System Access API,适合处理用户文件:
async function saveFile(content) {
try {
const handle = await window.showSaveFilePicker({
types: [{
description: 'Text Files',
accept: { 'text/plain': ['.txt'] }
}]
})
const writable = await handle.createWritable()
await writable.write(content)
await writable.close()
return handle
} catch (err) {
console.error('Error saving file:', err)
}
}
主要功能包括:
- 读取本地文件内容
- 保存修改到原文件
- 创建新文件并保存
- 获取目录内容列表
- 需要用户主动触发
服务端同步存储
结合Axios实现与服务端的同步存储:
import axios from 'axios'
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
})
// 封装存储方法
const storage = {
async set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value))
await api.post('/sync', { key, value })
} catch (error) {
console.error('Sync failed:', error)
}
},
async get(key) {
const localValue = localStorage.getItem(key)
if (!localValue) {
try {
const { data } = await api.get(`/sync?key=${key}`)
return data.value
} catch (error) {
console.error('Fetch failed:', error)
return null
}
}
return JSON.parse(localValue)
}
}
// 使用示例
storage.set('preferences', { theme: 'dark', fontSize: 14 })
.then(() => storage.get('preferences'))
.then(prefs => console.log(prefs))
加密存储方案
对于敏感数据,建议采用加密存储:
import CryptoJS from 'crypto-js'
const SECRET_KEY = 'my-secret-key-123'
const secureStorage = {
encrypt(data) {
return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString()
},
decrypt(ciphertext) {
const bytes = CryptoJS.AES.decrypt(ciphertext, SECRET_KEY)
return JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
},
set(key, value) {
localStorage.setItem(key, this.encrypt(value))
},
get(key) {
const ciphertext = localStorage.getItem(key)
return ciphertext ? this.decrypt(ciphertext) : null
}
}
// 使用示例
secureStorage.set('auth', { token: 'xyz789', expires: 3600 })
const authData = secureStorage.get('auth')
存储策略选择
不同场景下的存储方案选择建议:
- 用户偏好设置:localStorage + Vuex持久化插件
- 购物车数据:sessionStorage + 服务端备份
- 大型数据集:IndexedDB
- 敏感信息:加密存储 + 短期Cookie
- 离线应用数据:IndexedDB + Service Worker缓存
性能优化技巧
存储操作性能优化建议:
// 批量操作替代多次单次操作
function batchSave(items) {
const transaction = db.transaction('items', 'readwrite')
const store = transaction.objectStore('items')
items.forEach(item => {
store.put(item)
})
return new Promise((resolve, reject) => {
transaction.oncomplete = resolve
transaction.onerror = reject
})
}
// 使用Web Worker处理大型数据
const worker = new Worker('storage-worker.js')
worker.postMessage({
action: 'BULK_INSERT',
data: largeDataSet
})
其他优化手段:
- 对频繁读取的数据添加内存缓存层
- 使用debounce技术合并频繁的写入操作
- 对大型数据分块存储和读取
- 定期清理过期数据
跨标签页通信
利用存储事件实现标签页间通信:
// 发送方
localStorage.setItem('message', JSON.stringify({
type: 'DATA_UPDATE',
payload: { /* 数据 */ },
timestamp: Date.now()
}))
// 接收方
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
const message = JSON.parse(event.newValue)
if (message.type === 'DATA_UPDATE') {
// 处理数据更新
}
}
})
存储限制处理
处理存储空间不足的情况:
function checkStorageSpace() {
if ('storage' in navigator && 'estimate' in navigator.storage) {
return navigator.storage.estimate()
.then(estimate => {
const remaining = estimate.quota - estimate.usage
return remaining > 1024 * 1024 // 保留1MB空间
})
}
return Promise.resolve(true)
}
async function safeSetItem(key, value) {
const hasSpace = await checkStorageSpace()
if (!hasSpace) {
await clearOldData()
}
localStorage.setItem(key, value)
}
function clearOldData() {
// 实现按LRU策略清理旧数据
}
存储数据迁移
实现存储方案升级时的数据迁移:
function migrateLocalStorageToIndexedDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('AppDatabase', 2)
request.onupgradeneeded = (event) => {
const db = event.target.result
if (!db.objectStoreNames.contains('legacyData')) {
const store = db.createObjectStore('legacyData')
// 迁移localStorage数据
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i)
store.put(localStorage.getItem(key), key)
}
}
}
request.onsuccess = () => {
// 迁移完成后清理旧数据
localStorage.clear()
resolve()
}
request.onerror = reject
})
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:服务端渲染支持
下一篇:TypeScript深度集成