数据缓存(uni.setStorage)
数据缓存的基本概念
uni-app框架提供了uni.setStorage
方法用于将数据存储在本地缓存中。与浏览器环境下的localStorage
类似,但具有更好的跨平台兼容性。数据缓存是持久化存储,即使用户关闭应用后再次打开,数据依然存在。缓存以键值对形式存储,单个键最大支持1MB数据,总缓存大小在不同平台上有不同限制。
uni.setStorage的基本用法
uni.setStorage
方法接收一个对象参数,包含两个必要属性:
- key: 存储的键名
- data: 要存储的数据
// 存储字符串
uni.setStorage({
key: 'username',
data: '张三',
success: function() {
console.log('存储成功');
}
});
// 存储对象
uni.setStorage({
key: 'userInfo',
data: {
name: '李四',
age: 25,
gender: 'male'
}
});
// 存储数组
uni.setStorage({
key: 'todoList',
data: ['买菜', '写代码', '健身']
});
异步与同步存储
uni-app提供了异步和同步两种存储方式:
异步存储
uni.setStorage({
key: 'token',
data: 'abcdef123456',
success: () => {
console.log('token存储成功');
},
fail: (err) => {
console.error('存储失败:', err);
}
});
同步存储
try {
uni.setStorageSync('settings', {
theme: 'dark',
fontSize: 14
});
console.log('设置已保存');
} catch (e) {
console.error('保存失败:', e);
}
数据类型处理
uni.setStorage
可以存储多种数据类型,但需要注意:
- 基本类型:字符串、数字、布尔值直接存储
uni.setStorageSync('score', 100);
uni.setStorageSync('isVIP', true);
- 复杂类型:对象和数组会自动序列化为JSON字符串
const product = {
id: 1001,
name: '智能手机',
price: 2999
};
uni.setStorageSync('currentProduct', product);
- 特殊类型:Date对象、函数等需要先转换
// 存储日期
const now = new Date();
uni.setStorageSync('lastLogin', now.toISOString());
// 读取时转换回来
const lastLogin = new Date(uni.getStorageSync('lastLogin'));
缓存有效期管理
虽然uni-app的缓存没有内置过期机制,但可以通过以下方式实现:
// 存储带过期时间的数据
function setStorageWithExpire(key, data, expireDays) {
const record = {
data: data,
expire: Date.now() + expireDays * 24 * 60 * 60 * 1000
};
uni.setStorageSync(key, record);
}
// 读取并检查是否过期
function getStorageWithExpire(key) {
const record = uni.getStorageSync(key);
if (!record) return null;
if (Date.now() > record.expire) {
uni.removeStorageSync(key);
return null;
}
return record.data;
}
// 使用示例
setStorageWithExpire('sessionToken', 'token123', 7); // 7天后过期
const token = getStorageWithExpire('sessionToken');
批量操作与高级用法
批量存储数据
const batchData = {
userProfile: {name: '王五', age: 30},
appConfig: {theme: 'light', lang: 'zh-CN'},
recentSearches: ['uni-app', 'vue', '小程序']
};
Object.keys(batchData).forEach(key => {
uni.setStorageSync(key, batchData[key]);
});
存储加密数据
// 简单加密函数
function simpleEncrypt(data, key) {
return JSON.stringify(data).split('').map(c =>
String.fromCharCode(c.charCodeAt(0) ^ key.charCodeAt(0))
).join('');
}
// 存储加密数据
const sensitiveData = {bankCard: '622588******1234'};
uni.setStorageSync('encryptedData', simpleEncrypt(sensitiveData, 'secret'));
// 读取解密
const encrypted = uni.getStorageSync('encryptedData');
const decrypted = JSON.parse(simpleEncrypt(encrypted, 'secret'));
跨页面数据共享
利用缓存实现页面间数据传递:
// 页面A传递数据到页面B
// 页面A代码
uni.setStorageSync('shareData', {
from: 'PageA',
timestamp: Date.now(),
content: '这是要共享的数据'
});
// 页面B代码
onShow() {
const shared = uni.getStorageSync('shareData');
if (shared && shared.from === 'PageA') {
console.log('收到共享数据:', shared);
uni.removeStorageSync('shareData'); // 使用后清除
}
}
性能优化建议
- 避免频繁写入:合并多次写入操作
// 不推荐
for (let i = 0; i < 100; i++) {
uni.setStorageSync(`item_${i}`, data[i]);
}
// 推荐
const batch = {};
for (let i = 0; i < 100; i++) {
batch[`item_${i}`] = data[i];
}
uni.setStorageSync('batchData', batch);
- 合理设置缓存大小:监控缓存使用情况
function checkStorageUsage() {
const keys = uni.getStorageInfoSync().keys;
let total = 0;
keys.forEach(key => {
const data = uni.getStorageSync(key);
total += JSON.stringify(data).length;
});
console.log(`当前缓存使用: ${total}字节`);
return total;
}
- 定期清理无用缓存
function cleanUpStorage() {
const { keys } = uni.getStorageInfoSync();
const now = Date.now();
keys.forEach(key => {
if (key.startsWith('temp_')) {
const data = uni.getStorageSync(key);
if (data.expire && data.expire < now) {
uni.removeStorageSync(key);
}
}
});
}
实际应用场景
用户登录状态保持
// 登录成功后
uni.setStorageSync('auth', {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
userInfo: {
userId: '123',
username: 'user1'
},
loginTime: Date.now()
});
// 应用启动时检查
onLaunch() {
const auth = uni.getStorageSync('auth');
if (auth && auth.token) {
// 自动登录逻辑
this.checkTokenValid(auth.token).then(valid => {
if (!valid) {
uni.removeStorageSync('auth');
uni.redirectTo({url: '/pages/login/login'});
}
});
}
}
表单草稿保存
// 保存表单草稿
function saveFormDraft(formData) {
uni.setStorage({
key: 'draft_' + this.formId,
data: formData,
success: () => {
uni.showToast({title: '草稿已保存', icon: 'success'});
}
});
}
// 恢复表单草稿
function loadFormDraft() {
const draft = uni.getStorageSync('draft_' + this.formId);
if (draft) {
this.formData = draft;
uni.showModal({
title: '检测到未提交的草稿',
content: '是否恢复上次编辑的内容?',
success: (res) => {
if (!res.confirm) {
uni.removeStorageSync('draft_' + this.formId);
}
}
});
}
}
应用配置持久化
// 默认配置
const defaultSettings = {
theme: 'light',
fontSize: 16,
notification: true
};
// 加载用户配置
function loadSettings() {
const userSettings = uni.getStorageSync('userSettings') || {};
return {...defaultSettings, ...userSettings};
}
// 保存用户配置
function saveSettings(settings) {
uni.setStorageSync('userSettings', settings);
uni.$emit('settingsChanged', settings);
}
// 监听配置变化
uni.$on('settingsChanged', (settings) => {
if (settings.theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
});
常见问题与解决方案
数据存储失败排查
- 检查键名合法性:避免使用特殊字符
// 错误示例
uni.setStorageSync('user-data', value); // 可能在某些平台有问题
// 正确示例
uni.setStorageSync('userData', value);
- 处理存储空间不足
try {
uni.setStorageSync('largeData', bigData);
} catch (e) {
if (e.errMsg.includes('exceed')) {
// 清理旧缓存或提示用户
cleanOldCache();
}
}
数据更新策略
// 使用版本控制管理缓存数据
const CACHE_VERSION = 'v1.2';
function getCache(key) {
const cached = uni.getStorageSync(key);
if (cached && cached.version === CACHE_VERSION) {
return cached.data;
}
return null;
}
function setCache(key, data) {
uni.setStorageSync(key, {
version: CACHE_VERSION,
data: data,
timestamp: Date.now()
});
}
多Tab页数据同步
// 主页面代码
uni.setStorageSync('sharedCount', 0);
// 监听storage变化
uni.onStorageChange((res) => {
if (res.key === 'sharedCount') {
this.count = res.newValue;
}
});
// 修改数据
function increment() {
const count = uni.getStorageSync('sharedCount') || 0;
uni.setStorageSync('sharedCount', count + 1);
}
平台差异与兼容性
不同平台对uni.setStorage
的实现有细微差异:
-
微信小程序:
- 单个key最大1MB
- 总缓存上限10MB
- 会进行JSON.stringify序列化
-
H5:
- 使用localStorage实现
- 总缓存通常5MB
- 存储非字符串会自动调用toString()
-
App:
- iOS可能更严格限制
- 支持更大的存储空间
- 性能优于小程序
测试代码:
function testStorageLimits() {
const testData = {data: new Array(1024 * 1024).join('a')}; // ~1MB
try {
uni.setStorageSync('sizeTest', testData);
console.log('1MB存储测试通过');
uni.removeStorageSync('sizeTest');
} catch (e) {
console.warn('1MB存储测试失败:', e);
}
}
安全注意事项
-
敏感信息处理:
- 避免存储密码、支付信息等
- 必要时使用加密存储
-
XSS防护:
// 从缓存读取HTML内容时进行转义
function safeGetHTML(key) {
const html = uni.getStorageSync(key);
return html.replace(/</g, '<').replace(/>/g, '>');
}
- 用户隐私合规:
// 提供清除个人数据的选项
function clearUserData() {
const { keys } = uni.getStorageInfoSync();
keys.forEach(key => {
if (key.startsWith('user_')) {
uni.removeStorageSync(key);
}
});
}
调试技巧
- 查看所有缓存键
const { keys, currentSize, limitSize } = uni.getStorageInfoSync();
console.table(keys.map(key => ({
key,
size: JSON.stringify(uni.getStorageSync(key)).length
})));
- 模拟缓存数据(开发环境)
// 开发时预填充测试数据
if (process.env.NODE_ENV === 'development') {
if (!uni.getStorageSync('mockDataLoaded')) {
uni.setStorageSync('products', [
{id: 1, name: '测试商品1', price: 100},
{id: 2, name: '测试商品2', price: 200}
]);
uni.setStorageSync('mockDataLoaded', true);
}
}
- 性能测试
// 测试存储速度
function testStorageSpeed() {
const start = Date.now();
const testData = {value: Array(10000).fill(0).map((_, i) => i)};
for (let i = 0; i < 100; i++) {
uni.setStorageSync(`perfTest_${i}`, testData);
}
const duration = Date.now() - start;
console.log(`存储100次平均耗时: ${duration / 100}ms`);
// 清理测试数据
for (let i = 0; i < 100; i++) {
uni.removeStorageSync(`perfTest_${i}`);
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn