数据缓存与本地存储优化
数据缓存与本地存储优化
uni-app 开发中,合理利用数据缓存和本地存储能显著提升应用性能。从简单的变量缓存到复杂的数据库操作,不同场景需要选择合适方案。
本地缓存与持久化存储区别
uni-app 提供了两种主要存储方式:
- 本地缓存:uni.setStorage/uni.getStorage,数据保存在内存中,应用关闭后可能被系统清理
- 持久化存储:uni.setStorageSync/uni.getStorageSync,数据写入设备存储,长期保留
// 临时缓存示例
uni.setStorage({
key: 'tempData',
data: { timestamp: Date.now() },
success: () => console.log('缓存成功')
})
// 持久化存储示例
try {
uni.setStorageSync('userToken', 'abc123xyz')
} catch (e) {
console.error('存储失败', e)
}
缓存策略设计
1. 数据过期机制
为缓存数据添加时间戳,定期验证有效性:
function setCacheWithExpire(key, data, expireHours) {
const cacheObj = {
data: data,
expire: Date.now() + expireHours * 60 * 60 * 1000
}
uni.setStorageSync(key, JSON.stringify(cacheObj))
}
function getCacheWithExpire(key) {
const cacheStr = uni.getStorageSync(key)
if (!cacheStr) return null
const cacheObj = JSON.parse(cacheStr)
if (Date.now() > cacheObj.expire) {
uni.removeStorageSync(key)
return null
}
return cacheObj.data
}
2. 缓存分级策略
- 一级缓存:内存缓存,使用全局变量
- 二级缓存:本地存储,使用uni.storage
- 三级缓存:服务端请求
const memoryCache = {}
function getData(key) {
// 1. 检查内存缓存
if (memoryCache[key]) return Promise.resolve(memoryCache[key])
// 2. 检查本地存储
const localData = getCacheWithExpire(key)
if (localData) {
memoryCache[key] = localData
return Promise.resolve(localData)
}
// 3. 请求网络
return fetchDataFromServer(key).then(serverData => {
memoryCache[key] = serverData
setCacheWithExpire(key, serverData, 24)
return serverData
})
}
存储性能优化
1. 批量操作减少IO
// 低效写法
userList.forEach(user => {
uni.setStorageSync(`user_${user.id}`, user)
})
// 优化写法
const batchData = {}
userList.forEach(user => {
batchData[`user_${user.id}`] = user
})
uni.setStorageSync('all_users', batchData)
2. 数据压缩存储
对于大型JSON数据,可以先压缩:
import lzString from 'lz-string'
function setCompressedData(key, data) {
const compressed = lzString.compressToUTF16(JSON.stringify(data))
uni.setStorageSync(key, compressed)
}
function getCompressedData(key) {
const compressed = uni.getStorageSync(key)
return JSON.parse(lzString.decompressFromUTF16(compressed))
}
特殊场景处理
1. 图片缓存方案
function cacheImage(url) {
return new Promise((resolve) => {
const fileName = url.split('/').pop()
const cacheKey = `img_${fileName}`
// 检查已有缓存
const cachedPath = uni.getStorageSync(cacheKey)
if (cachedPath) {
resolve(cachedPath)
return
}
// 下载并缓存
uni.downloadFile({
url,
success: (res) => {
if (res.statusCode === 200) {
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
uni.setStorageSync(cacheKey, saveRes.savedFilePath)
resolve(saveRes.savedFilePath)
}
})
}
}
})
})
}
2. 列表分页缓存
const PAGE_SIZE = 10
function cachePageData(listKey, pageNum, data) {
const pageKey = `${listKey}_page_${pageNum}`
uni.setStorageSync(pageKey, data)
// 更新列表元信息
const meta = uni.getStorageSync(`${listKey}_meta`) || {}
meta.lastUpdate = Date.now()
meta.totalPages = Math.max(meta.totalPages || 0, pageNum)
uni.setStorageSync(`${listKey}_meta`, meta)
}
function getCachedPage(listKey, pageNum) {
const pageKey = `${listKey}_page_${pageNum}`
return uni.getStorageSync(pageKey)
}
跨平台兼容处理
不同平台存储限制不同:
- 微信小程序:单个key最大1MB,总上限10MB
- H5:依赖浏览器实现,通常5MB左右
- App:基本无限制
function checkStorageSpace() {
if (uni.getSystemInfoSync().platform === 'android') {
// Android特殊处理
return true
}
try {
uni.setStorageSync('test_space', new Array(1024 * 1024).join('a'))
uni.removeStorageSync('test_space')
return true
} catch (e) {
return false
}
}
数据安全考虑
1. 敏感信息加密
import CryptoJS from 'crypto-js'
const SECRET_KEY = 'your-secret-key-123'
function encryptData(data) {
return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString()
}
function decryptData(cipherText) {
const bytes = CryptoJS.AES.decrypt(cipherText, SECRET_KEY)
return JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
}
2. 自动清理机制
function autoCleanStorage() {
const now = Date.now()
const allKeys = uni.getStorageInfoSync().keys
allKeys.forEach(key => {
if (key.startsWith('cache_')) {
const data = uni.getStorageSync(key)
if (data && data.expire && data.expire < now) {
uni.removeStorageSync(key)
}
}
})
}
// 应用启动时执行
autoCleanStorage()
性能监控与调试
添加存储操作日志:
const storageLogger = {
log: [],
maxSize: 100
}
function wrapStorage() {
const originalSet = uni.setStorageSync
uni.setStorageSync = function(key, data) {
storageLogger.log.push({
type: 'set',
key,
size: JSON.stringify(data).length,
time: Date.now()
})
if (storageLogger.log.length > storageLogger.maxSize) {
storageLogger.log.shift()
}
return originalSet.call(uni, key, data)
}
}
// 初始化包装
wrapStorage()
本地数据库方案
对于复杂数据结构,考虑使用本地数据库:
// 使用indexedDB(H5)
function initDB() {
return new Promise((resolve) => {
const request = indexedDB.open('myDatabase', 1)
request.onupgradeneeded = (event) => {
const db = event.target.result
if (!db.objectStoreNames.contains('products')) {
db.createObjectStore('products', { keyPath: 'id' })
}
}
request.onsuccess = (event) => {
resolve(event.target.result)
}
})
}
// 使用SQLite(App端)
function initSQLite() {
plus.sqlite.openDatabase({
name: 'mydb',
path: '_doc/mydb.db',
success: (e) => {
console.log('数据库打开成功')
}
})
}
缓存更新策略
实现智能缓存更新机制:
const cacheStrategies = {
// 定时更新
TIMED: (key, getData, interval) => {
const lastUpdate = uni.getStorageSync(`${key}_lastUpdate`) || 0
if (Date.now() - lastUpdate > interval) {
return getData().then(data => {
uni.setStorageSync(key, data)
uni.setStorageSync(`${key}_lastUpdate`, Date.now())
return data
})
}
return Promise.resolve(uni.getStorageSync(key))
},
// 版本号更新
VERSIONED: (key, getData, currentVersion) => {
const cachedVersion = uni.getStorageSync(`${key}_version`)
if (cachedVersion !== currentVersion) {
return getData().then(data => {
uni.setStorageSync(key, data)
uni.setStorageSync(`${key}_version`, currentVersion)
return data
})
}
return Promise.resolve(uni.getStorageSync(key))
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:页面渲染性能优化
下一篇:避免频繁的 setData 操作