数据的港湾:本地存储 `Storage` API
数据的港湾:本地存储 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
工具模块:
-
在
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 };
-
在业务代码中使用:
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模块,让你的开发效率和代码质量迈上一个新的台阶。
我们下篇见!