数据的港湾:本地存储 Storage API

所属专栏:《微信小程序-实战笔记30讲》
作者:码力无边

前言

在上一讲,我们学会了如何通过wx.request从服务器获取动态数据。这解决了数据“来源”的问题。但是,并不是所有数据都需要每次打开小程序时都去服务器重新请求一次。

想象一下这些场景:

  • 用户的登录凭证(Token),总不能让用户每次打开小程序都重新登录吧?
  • 用户的搜索历史记录,关闭小程序再打开应该还在。
  • 一些不常变动的应用配置信息,没必要每次都从网络加载。

对于这些需要在本地进行持久化存储的数据,小程序为我们提供了一个简单而强大的“数据港湾”——本地存储(Storage)API

它就像浏览器里的LocalStorage,允许我们在用户的设备上存储键值对(Key-Value)数据。这些数据会一直存在,除非用户手动清除小程序缓存,或者我们用代码主动删除它。

今天,我们将学习如何使用Storage API来高效地管理小程序本地数据,为你的应用打造一个可靠的“本地小仓库”。

一、同步 vs 异步:两种存储方式的选择

小程序的本地存储API设计得非常人性化,它为几乎每一个操作都提供了同步异步两个版本的接口。

  • 同步接口:方法名以Sync结尾,如wx.setStorageSync

    • 特点:代码会“卡”在这一行,直到存储/读取操作完成,才会继续执行下面的代码。执行结果直接通过函数返回值获取。
    • 优点:代码书写简单、直观。
    • 缺点:如果存储的数据量很大,可能会阻塞主线程,导致界面卡顿。
    • 适用场景:存储少量、关键的、后续代码立即需要用到的数据(如登录Token)。
  • 异步接口:方法名不带Sync,如wx.setStorage

    • 特点:调用后立即返回,不会等待操作完成。操作结果通过success, fail, complete等回调函数来获取。
    • 优点:不会阻塞主线程,体验更流畅,适合处理大数据。
    • 缺点:代码写法稍复杂(回调地狱),或需要配合Promise使用。
    • 适用场景:存储/读取的数据量较大,或对性能要求较高的场景。

最佳实践:对于绝大多数小程序开发场景,数据量通常不大,使用同步接口更加方便快捷。但当你知道要处理的数据可能很大(如缓存整个文章内容)时,应优先考虑使用异步接口。

二、核心API详解与实战

本地存储的核心操作无非就是“增删改查”。

1. 存储数据:wx.setStorageSync(key, data) / wx.setStorage(Object object)

同步存储:
这是我们最常用的方式。key是数据的“名字”(字符串),data是要存储的内容(可以是字符串、数字、对象、数组等)。

// 存储一个简单的字符串
wx.setStorageSync('username', '码力无边');
// 存储一个复杂的对象
const userInfo = {
userId: '1001',
avatar: 'url/to/avatar.png',
level: 99
};
wx.setStorageSync('userInfo', userInfo);
console.log('用户信息已同步存储');

小程序会自动将非字符串类型的数据进行JSON.stringify处理后存储。

异步存储:

wx.setStorage({
key: "searchHistory",
data: ['小程序开发', 'Vue.js', 'React'],
success: () =>
{
console.log('搜索历史已异步存储成功');
},
fail: () =>
{
console.error('搜索历史存储失败');
}
})
2. 读取数据:wx.getStorageSync(key) / wx.getStorage(Object object)

同步读取:
如果key存在,返回对应的数据;如果不存在,则返回一个空字符串''

// 读取用户名
const username = wx.getStorageSync('username');
if (username) {
console.log(`欢迎回来, ${username
}`);
// 输出:欢迎回来, 码力无边
} else {
console.log('用户未设置用户名');
}
// 读取用户信息对象
const userInfo = wx.getStorageSync('userInfo');
console.log(userInfo.level);
// 输出:99
// 读取一个不存在的key
const nonExistentData = wx.getStorageSync('someRandomKey');
console.log(nonExistentData);
// 输出:'' (空字符串)

异步读取:

wx.getStorage({
key: 'searchHistory',
success: (res) =>
{
// res.data 中是读取到的数据
console.log('异步读取到的搜索历史:', res.data);
},
fail: () =>
{
console.log('读取搜索历史失败或不存在');
}
})
3. 删除数据:wx.removeStorageSync(key) / wx.removeStorage(Object object)

当用户退出登录或某些数据不再需要时,我们可以将其从本地存储中移除。

同步删除:

// 用户退出登录时,清除用户信息
wx.removeStorageSync('userInfo');
// 再次尝试读取,会返回空字符串
const userInfo = wx.getStorageSync('userInfo');
console.log(userInfo);
// 输出:''

异步删除:

wx.removeStorage({
key: 'searchHistory',
success: () =>
{
console.log('异步删除搜索历史成功');
}
})
4. 清空所有数据:wx.clearStorageSync() / wx.clearStorage()

这是一个“毁灭性”的操作,它会清空当前小程序在本地存储的所有数据。请谨慎使用!

同步清空:

// 在应用的“设置”页面提供一个“清除缓存”的功能
function clearAllCache() {
try {
wx.clearStorageSync();
wx.showToast({ title: '缓存已清除'
});
} catch (e) {
wx.showToast({ title: '清除失败', icon: 'none'
});
}
}

三、管理与限制

  • 存储容量限制:每个小程序本地存储的总大小限制为10MB。对于绝大多数应用来说是足够的。可以通过wx.getStorageInfo / wx.getStorageInfoSync来获取当前已使用空间大小、所有key的列表等信息。
  • 数据类型:可以存储原生类型、Date、以及可以被JSON.stringify的Object和Array。不能存储 Function、RegExp、Error等
  • 作用域:本地存储是以小程序为维度的。同一个微信用户,在不同小程序中,其本地存储是完全隔离的。同一个小程序,在不同用户设备上,其本地存储也是隔离的。

四、实战场景:封装一个Storage工具类

与网络请求类似,直接在业务代码中散乱地调用wx.setStorageSync('key', value)会导致key的管理混乱。一个更好的实践是,将所有Storage操作封装成一个工具类或模块,统一管理所有的key

动手实践 - 创建storage.js工具模块:

  1. utils文件夹下新建storage.js文件。

    // utils/storage.js
    // 定义所有需要用到的key,方便管理和避免拼写错误
    const KEYS = {
    TOKEN: 'token',
    USER_INFO: 'user_info',
    SEARCH_HISTORY: 'search_history'
    };
    const set = (key, data) =>
    {
    try {
    wx.setStorageSync(key, data);
    } catch (e) {
    console.error(`存储[${key
    }]失败:`, e);
    }
    };
    const get = (key) =>
    {
    try {
    return wx.getStorageSync(key);
    } catch (e) {
    console.error(`读取[${key
    }]失败:`, e);
    return null;
    }
    };
    const remove = (key) =>
    {
    try {
    wx.removeStorageSync(key);
    } catch (e) {
    console.error(`删除[${key
    }]失败:`, e);
    }
    }
    export default {
    KEYS,
    set,
    get,
    remove
    };
  2. 在业务代码中使用:

    import storage from '../../utils/storage';
    // 存储Token
    storage.set(storage.KEYS.TOKEN, 'your-long-long-token');
    // 读取用户信息
    const userInfo = storage.get(storage.KEYS.USER_INFO);
    // 删除Token
    storage.remove(storage.KEYS.TOKEN);

    通过这种方式,代码的可读性和可维护性大大增强。

结语

今天,我们为小程序建立了一个坚实可靠的“数据港湾”——本地存储。我们学会了:

  • 区分同步异步API,并根据场景做出选择。
  • 熟练使用增、删、改、查四种核心Storage操作。
  • 理解了本地存储的容量限制作用域
  • 通过封装工具模块来优雅地管理本地数据。

到现在为止,我们已经掌握了小程序开发中大量的“积木块”——组件、API、路由、网络、存储。但是,当应用变得越来越复杂时,如何高效地组织和复用这些“积木块”,避免代码的冗余和臃肿呢?

下一讲,我们将进入一个非常重要的话题:代码复用的艺术——自定义组件。我们将学习如何创建属于自己的、可复用的UI模块,让你的开发效率和代码质量迈上一个新的台阶。

我们下篇见!

posted on 2025-09-27 10:55  ycfenxi  阅读(9)  评论(0)    收藏  举报