统一前端本地存储层工具
pnpm install @stevenleep/storage
内部依赖
pnpm --filter <YourPackageName> add @stevenleep/storage
@*表示默认同步最新版本
pnpm --filter <YourPackageName> add @stevenleep/storage@* #
pnpm --filter <YourPackageName> add @stevenleep/storage@\* # mac-zsh 终端
import EnhancedStorage from "@stevenleep/storage";
const xxStorage = new EnhancedStorage();
// EnhancedStorage设计时完全遵从StorageAPI
// 写数据,默认存在localstorage中
// 可更改位置,稍后提及
xxStorage.setItem("foo", "bar");
xxStorage.setItem("bar", "baz");
// 获取数据
xxStorage.getItem("foo"); // bar
xxStorage.getItem("bar"); // baz
// 删除
xxStorage.removeItem("foo");
xxStorage.removeItem("bar");
// 清空
xx.clear();
namespace 可以在调用当前时为每一个 key 都增加一个前前缀,默认的前缀为:@app/
, 这意味着如果不做任何处理,你的 key 格式如下:
// 你在存储和获取时候的key为a,实际存储到数据层的key为 @app/a
xxStorage.setItem("a");
这样更改 namespace
import EnhancedStorage from "@stevenleep/storage";
const doActionStorage = new EnhancedStorage({
namespace: "__app__/", // 后续的key前面都有一个 __app__/
});
内部默认实现了以下存储层
export enum StorageType {
LocalStorage = "localStorage",
SessionStorage = "sessionStorage",
MemoryStorage = "memoryStorage",
Cookie = "cookie",
}
这样替换存储层
import EnhancedStorage, { StorageType } from "@stevenleep/storage";
const xxStorage = new EnhancedStorage({
storage: StorageType.SessionStorage, // 使用SessionStorage存储
});
为所有的实例增加一种存储层
import { Storages } from "@stevenleep/storage";
Storages.set("key", {
getItem: function (key) {
// ...
},
// ...
});
完全替换
import EnhancedStorage, { BaseStorageInterface } from "@stevenleep/storage";
class CusterStorage implements BaseStorageInterface {
// ...
}
const customStorage = new EnhancedStorage({
storage: new CusterStorage(),
});
依赖关系如下
- EnhancedStorage 对外暴露的存储层
-
extends
BaseStorage 实现了最基础的存储层能力,数据的增删查清空等,以及抹平多种本地存储 API-
deps:data
: AbsStorage 真实的数据存储位置,即 localStorage/sessionStorage/cookie/memoryStorage
-
-
deps
BaseReactive 实现了数据变更时候的通知机制
-
import { BaseStorage } from "@stevenleep/storage";
class MyStorage extends BaseStorage {
constructor() {
super(); // 默认使用localStorage
// super({
// storage: CustomStorage, // 自定义的存储层
// namespace: '' // 自定义namespace
// )
}
}
监听某个 key 值的变化
import EnhancedStorage from "@stevenleep/storage";
const storage = new EnhancedStorage();
storage.setItem("a", "aaaa");
function handleChange(newValue, oldValue) {
// ...
}
const cancel = storage.observer.subscribe("a", handleChange);
// 取消
cancel(); // 通过返回的cancel函数
// 通过取消API
storage.observer.unsubscribe("a", handleChange);
监听整个 Storage 层数据变化
import EnhancedStorage from "@stevenleep/storage";
const storage = new EnhancedStorage();
function handleChange(newValue, oldValue, key) {
// ...
}
storage.observer.subscribeStateChange(handleChange); // 订阅
storage.observer.unsubscribeStateChange(handleChange); // 取消
给所由订阅者广播 - 默认清空使用
import EnhancedStorage from "@stevenleep/storage";
const storage = new EnhancedStorage();
storage.observer.broadcast(newvalue, oldvalue);
跨实例通信 - 跨服聊天
一些时候我们会为可能会在 LocalStorage 的逻辑中增加对 SessionStorage/Cookie 的监听,类似场景下使用实例上 subscribeWithScope
方法即可实现
import EnhancedStorage, { StorageType } from "@stevenleep/storage";
const enhancedLocalStorageNamespace = "@app1/";
const enhancedLocalStorage = new EnhancedStorage({
namespace: enhancedLocalStorageNamespace,
storage: StorageType.LocalStorage,
});
const enhancedSessionStorageNamespace = "@app2/";
const enhancedSessionStorage = new EnhancedStorage({
namespace: enhancedSessionStorageNamespace,
storage: StorageType.SessionStorage,
});
enhancedLocalStorage.observer.subscribeWithScope(
enhancedSessionStorageNamespace, // 目标存储层的namespace
"a", // 下面的key
function (newValue, oldValue) {
// ...
}
);
enhancedSessionStorage.setItem("a", "20"); // 存储数值并会触发上面👆监听