存储(四种存储全景)
插件能碰到四种存储,先选对再写代码:
| 存储 | 命名空间 | 持久化位置 | 三层支持 | 典型用途 |
|---|---|---|---|---|
wadLogicLayer.storage | wx storage,key 前缀 __wad_<id>_ | 小程序 storage | 逻辑层全量(Promise+Sync);面板经 logicLayer.storage 仅 Promise;渲染层 — | 跟着小程序走的业务数据 |
wadPanelLayer.storage | 插件私有 | 宿主 JSON:plugins/<id>/store/panel.json | 仅面板(Promise) | 面板配置/上次输入 |
wadPanelLayer.localStorage / sessionStorage | Web Storage,key 前缀 __wad_<id>_ | 面板 WebView(sessionStorage 随面板关闭消失) | 仅面板 | 大文本草稿、面板会话态 |
wadRenderLayer.localStorage / sessionStorage | Web Storage,key 前缀 __wad_<id>_ | 页面 WebView | 仅渲染层 | 渲染层会话态 |
sharedStorage.app / global | 插件私有 | 宿主 JSON:plugins/<id>/store/shared.json | 三层全部 | 跨层共享状态 |
本页你将学到
- 四种存储各自的命名空间与持久化位置;
- 逻辑层 storage 的 Promise + Sync 双形态;
- sharedStorage 的 app/global 作用域与 watch;
- storageWrite 事件的两条铁律。
wadLogicLayer.storage(wx storage,插件命名空间)
业务小程序的 wx storage,插件 key 自动加前缀 __wad_<id>_<key>,与业务数据互不污染。keys() 返回的 key 不含前缀。
| 方法 | 逻辑层 | 面板(经 wadPanelLayer.logicLayer.storage) |
|---|---|---|
get(key) | Promise(无值 resolve undefined) | Promise(底层 wx.getStorageSync,无值返回 '') |
set(key, value) | Promise(任意可序列化值) | Promise |
remove(key) | Promise | Promise |
keys() | Promise(本插件全部 key) | Promise |
clear() | Promise | Promise |
getSync/setSync/removeSync/keysSync/clearSync | 同步版 | 抛 E_LAYER_ONLY(同步版只能在逻辑层本地调) |
js
// 逻辑层:同步或 Promise 随意
wadLogicLayer.storage.setSync('lastRoute', 'pages/index/index');
var v = wadLogicLayer.storage.getSync('lastRoute');js
(async () => {
// 面板:只有 Promise(走 logicLayer 代理)
await wadPanelLayer.logicLayer.storage.set('note', '面板写的');
const keys = await wadPanelLayer.logicLayer.storage.keys(); // ['note']
})();wadPanelLayer.storage(面板私有,宿主 JSON 持久化)
面板每次打开是全新 WebView,跨会话状态放这里。
js
(async () => {
// 面板层
const cfg = (await wadPanelLayer.storage.get('cfg')) || { kw: '', method: 'GET' };
await wadPanelLayer.storage.set('cfg', cfg);
const ks = await wadPanelLayer.storage.keys();
await wadPanelLayer.storage.remove('cfg');
await wadPanelLayer.storage.clear();
})();Web Storage(面板/渲染层各自的 localStorage / sessionStorage)
标准 Web Storage 接口(getItem/setItem/removeItem/clear/key/length),自动加插件前缀,只操作自己的 key:
js
// 面板层
wadPanelLayer.localStorage.setItem('draft', bigText); // 面板重开仍在
wadPanelLayer.sessionStorage.setItem('scroll', '120'); // 面板关闭即消失
// 渲染层
wadRenderLayer.localStorage.setItem('marked', '1'); // 页面 WebView 内持久sharedStorage(跨层共享,宿主持久化 + watch)
三个层看到的是同一份数据(wadLogicLayer.sharedStorage / wadRenderLayer.sharedStorage / wadPanelLayer.sharedStorage)。宿主落盘在 plugins/<id>/store/shared.json({rev, app:{<appid>:{...}}, global:{...}}):
- app 作用域:按小程序 appid 隔离——同插件在 A 小程序写的值,B 小程序看不到;
- global 作用域:跨小程序共享。
| 方法(app/global 同构) | 签名 | 说明 |
|---|---|---|
get(key) | Promise<any> | 取值 |
set(key, value) | Promise | 写值(触发 fan-out 与 watch) |
remove(key) | Promise | 删除 |
keys() | Promise<string[]> | 本作用域全部 key |
clear() | Promise | 清空本作用域 |
watch(key, fn) | → unwatch() | 订阅变更;key 传 '*' 监听全部 |
js
(async () => {
// 逻辑层写
await wadLogicLayer.sharedStorage.app.set('lastRoute', 'pages/cart/cart');
await wadLogicLayer.sharedStorage.global.set('installAt', Date.now());
// 面板读
const route = await wadPanelLayer.sharedStorage.app.get('lastRoute');
// 渲染层写,逻辑层也能立即看到
await wadRenderLayer.sharedStorage.app.set('domChanged', true);
})();watch 与 change 对象
js
var unwatch = wadLogicLayer.sharedStorage.app.watch('lastRoute', function (value, change) {
// value = 新值
// change = 变更详情(见下表)
});
unwatch(); // 解除订阅
// 监听全部 key
wadLogicLayer.sharedStorage.global.watch('*', function (value, change) { /* … */ });change 对象字段:
| 字段 | 说明 |
|---|---|
key | 变更的 key |
op | 'set' | 'remove' | 'clear' |
scope | 'app' | 'global' |
value | 新值(remove/clear 时为 null) |
rev | 作用域修订号(单调递增) |
at | 宿主时间戳 |
plugin | 触发写入的插件 id |
from | 写入发生层:'logic' | 'render' | 'panel' |
instanceId | 写入实例(逻辑层 'logic';渲染层 render-xxxxxx;面板 clientId) |
appid | 仅 app 作用域:写入发生的小程序 |
fan-out 范围:本插件的面板 + 逻辑层 + 渲染层(跨插件不可见)。共享状态的更多实践见 sharedStorage。
storageWrite:业务 storage 写入事件
业务代码调 wx.setStorage* / removeStorage* / clearStorage* 时,逻辑层与面板会收到 storageWrite 事件(渲染层没有 wx storage 通道,收不到)(见 事件系统):
js
// 逻辑层
wadLogicLayer.onStorageWrite(function (e) {
// e = {op: 'set'|'remove'|'clear', key, value?, plugin}
if (e.key === 'session_token') wadLogicLayer.log('token 变了:' + e.value);
});两条铁律:
- 插件自己的命名空间(
__wad_前缀)写入不触发storageWrite(防自反馈); - 绕过 wx API 的原生写入不可见——
storageWrite只覆盖wx.setStorage* / removeStorage* / clearStorage*。
怎么选
| 场景 | 用哪个 |
|---|---|
| 面板 UI 状态(筛选条件、上次输入) | wadPanelLayer.storage |
| 跟着小程序业务走的数据(路由栈、token 快照) | wadLogicLayer.storage(逻辑层优先用 *Sync) |
| 面板 ↔ 逻辑层 ↔ 渲染层要共享、且希望变更可订阅 | sharedStorage.app |
| 跨小程序的插件级状态(安装时间、全局开关) | sharedStorage.global |
| 临时草稿 | 各层 Web Storage(sessionStorage 随生命周期消失) |