阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 数据缓存(uni.setStorage)

数据缓存(uni.setStorage)

作者:陈川 阅读数:54609人阅读 分类: uni-app

数据缓存的基本概念

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可以存储多种数据类型,但需要注意:

  1. 基本类型:字符串、数字、布尔值直接存储
uni.setStorageSync('score', 100);
uni.setStorageSync('isVIP', true);
  1. 复杂类型:对象和数组会自动序列化为JSON字符串
const product = {
  id: 1001,
  name: '智能手机',
  price: 2999
};
uni.setStorageSync('currentProduct', product);
  1. 特殊类型: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'); // 使用后清除
  }
}

性能优化建议

  1. 避免频繁写入:合并多次写入操作
// 不推荐
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);
  1. 合理设置缓存大小:监控缓存使用情况
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;
}
  1. 定期清理无用缓存
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');
  }
});

常见问题与解决方案

数据存储失败排查

  1. 检查键名合法性:避免使用特殊字符
// 错误示例
uni.setStorageSync('user-data', value); // 可能在某些平台有问题

// 正确示例
uni.setStorageSync('userData', value);
  1. 处理存储空间不足
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的实现有细微差异:

  1. 微信小程序

    • 单个key最大1MB
    • 总缓存上限10MB
    • 会进行JSON.stringify序列化
  2. H5

    • 使用localStorage实现
    • 总缓存通常5MB
    • 存储非字符串会自动调用toString()
  3. 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);
  }
}

安全注意事项

  1. 敏感信息处理

    • 避免存储密码、支付信息等
    • 必要时使用加密存储
  2. XSS防护

// 从缓存读取HTML内容时进行转义
function safeGetHTML(key) {
  const html = uni.getStorageSync(key);
  return html.replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
  1. 用户隐私合规
// 提供清除个人数据的选项
function clearUserData() {
  const { keys } = uni.getStorageInfoSync();
  keys.forEach(key => {
    if (key.startsWith('user_')) {
      uni.removeStorageSync(key);
    }
  });
}

调试技巧

  1. 查看所有缓存键
const { keys, currentSize, limitSize } = uni.getStorageInfoSync();
console.table(keys.map(key => ({
  key,
  size: JSON.stringify(uni.getStorageSync(key)).length
})));
  1. 模拟缓存数据(开发环境)
// 开发时预填充测试数据
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);
  }
}
  1. 性能测试
// 测试存储速度
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

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌