存储 API
@plasmohq/storage 是来自 plasmo 的一个实用程序库,它抽象了浏览器扩展可用的持久存储 API。当扩展存储 API 不可用时,它会回退到 localStorage,允许在扩展页面、内容脚本、后台服务工作者和网页之间同步状态。
如果在 Plasmo 框架 项目中作为依赖项使用,此库将自动启用
storage权限
安装
pnpm install @plasmohq/storage该包导出以下模块,包括 ESM 和 CJS 格式:
| 模块 | 描述 |
|---|---|
@plasmohq/storage | 基础 存储 API |
@plasmohq/storage/secure | 安全存储 API |
@plasmohq/storage/hook | React Hook 存储 API |
使用示例
- 查看 with-storage 了解如何使用此库在选项和弹出窗口之间同步状态。
- 查看 with-redux 了解如何使用此库作为 Redux 持久层(对 MV3 至关重要)。
- 查看 MICE 了解此库与 WebRTC 集成以通过扩展在浏览器之间传输消息的实验性用例。
存储
基础存储 API 设计为易于使用。它可在每个扩展运行时中使用,例如后台服务工作者、内容脚本和扩展页面。
获取/设置数据无需 JSON.stringify/parse。只要您存储的数据是可序列化的(普通对象或原始类型),就可以存储:
import { Storage } from "@plasmohq/storage"
const storage = new Storage()
await storage.set("key", "value")
const data = await storage.get("key") // "value"
await storage.set("capt", { color: "red" })
const data2 = await storage.get("capt") // { color: "red" }自定义存储区域
存储区域默认为 “sync”,这意味着数据会在用户登录的所有 Chrome 实例之间同步。
您可以在 Chrome 存储 API 文档 中查看 Plasmo 支持的所有其他可能范围。
const storage = new Storage({
area: "local"
})自动复制数据到 localStorage
const storage = new Storage({
copiedKeyList: ["shield-modulation"]
})上面的代码将在与内容脚本或扩展页面一起使用时将数据复制到 Web localStorage。
监听(用于状态同步)
要监听使用存储 API 时的更改:
import { Storage } from "@plasmohq/storage"
const storage = new Storage()
await storage.set("serial-number", 47)
await storage.set("make", "plasmo-corp")
storage.watch({
"serial-number": (c) => {
console.log(c.newValue)
},
make: (c) => {
console.log(c.newValue)
}
})
await storage.set("serial-number", 96)
await storage.set("make", "PlasmoHQ")这可以用作在扩展中通信消息的层。我们在 with-redux 示例中演示了这一点。
注意: 当内容脚本在 ‘MAIN’ 世界中执行时,存储 API 不可用,因为它失去了对 Chrome 扩展 API 的访问权限。
安全存储
安全存储 API 扩展了存储功能,提供数据加密和解密功能,用于敏感密钥的静态冷存储。它利用 Web Crypto SubtleCrypto API,该 API 仅在安全上下文(HTTPS)中工作。
import { SecureStorage } from "@plasmohq/storage/secure"
const storage = new SecureStorage()
await storage.setPassword("roosevelt") // 唯一的区别
await storage.set("key", "value")
const data = await storage.get("key") // "value"
await storage.set("capt", { color: "red" })
const data2 = await storage.get("capt") // { color: "red" }React Hook API
Hook API 旨在简化扩展不同部分之间的状态同步工作流程。它有很多使用方式,但首先您需要将 hook 导入到 React 组件中:
import { useStorage } from "@plasmohq/storage/hook"监听并渲染值
const [hailingFrequency] = useStorage("hailing")
...
{hailingFrequency}使用自定义存储实例
import { Storage } from "@plasmohq/storage"
...
const [hailingFrequency] = useStorage({
key: "hailing",
instance: new Storage({
area: "local"
})
})渲染初始值但不持久化
“持久化”意味着写入内部存储器。
通过不持久化值,只有当存储中没有值时,此特定 hook 实例才会渲染给定的初始值。其他实例可以显示 undefined 或指定它们自己的初始值。详细说明:
给定一个设置静态初始值的 popup.tsx:
const [hailingFrequency, setHailingFrequency] = useStorage("hailing", "42")
...
<input value={hailingFrequency} onChange={(e) =>
setHailingFrequency(e.target.value)
}/> // "42"如果我们在 content.tsx 中订阅此键,我们将看到它为 undefined,直到使用定义的值调用 setHailingFrequency:
const [hailingFrequency] = useStorage("hailing")
return <p>{hailingFrequency}</p> // undefined如果我们在 options.tsx 中订阅此键,但使用不同的静态初始值,我们将看到该值:
const [hailingFrequency] = useStorage("hailing", "147")
return <p>{hailingFrequency}</p> // "147"使用上述设置,假设我们在任何实例中调用 setHailingFrequency("8472"),我们将看到所有实例现在都显示 “8472”,并且现在将跟踪存储中的值而不是初始值。
渲染并持久化初始值
通过使用函数而不是静态值,初始值将被持久化在存储内存中。初始化函数有一个参数,即存储中的现有值。如果没有值,则为 undefined。
假设我们有一个 popup.tsx,如果存储中没有任何内容,则将状态初始化为 “42”:
const [hailingFrequency, setHailingFrequency] = useStorage("hailing", (v) => v === undefined ? "42": v)
...
{hailingFrequency} // "42"然后,如果我们在 content.tsx 或 options.tsx 中创建一个新的 hook 实例,我们将看到持久化的初始值,而无需调用 setHailingFrequency:
const [hailingFrequency] = useStorage("hailing")
return <p>{hailingFrequency}</p> // "42"高级用法
在处理表单输入或实时输入时,您可能需要以下内容:
const [hailingFrequency, setHailingFrequency, {
setRenderValue,
setStoreValue,
remove
}] = useStorage("hailing")
return <>
<input value={hailingFrequency} onChange={(e) => setRenderValue(e.target.value)}/>
<button onClick={() => setStoreValue()}>
保存
</button>
<button onClick={() => remove()}>
删除
</button>
</>
在 Firefox 中使用
要在开发期间在 Firefox 上使用存储 API,您需要在清单中添加一个附加组件 ID,否则您将收到此错误:
错误:存储 API 无法与临时附加组件 ID 一起使用。请向您的清单添加显式的附加组件 ID。有关更多信息,请参阅 https://mzl.la/3lPk1aE。
要向清单添加附加组件 ID,请将此添加到您的 package.json:
"manifest": {
"browser_specific_settings": {
"gecko": {
"id": "your-id@example.com"
}
}
}附加组件 ID 的格式因清单版本而异。
- Manifest V2:
your-id@example.com - Manifest V3:
{ed7ba470-8e54-465e-825c-99712043e01c}(任何 UUID)
一旦您的扩展发布,package.json 文件中定义的附加组件 ID 应该 在您扩展的开发者页面中的 “技术细节 > UUID” 下显示。
注意: 开发期间使用的附加组件 ID(即在清单中定义的 ID)很可能是 Mozilla 在发布时分配给您的 ID。如果不是,并且为您生成了一个 ID,您将必须使用新的 ID 更新 package.json 文件。
附加组件 ID 是唯一的,同一个 ID 不能用于多个扩展(两个清单版本)。