Skip to Content
LaunchExt | Chrome 扩展开发平台 (Next.js + Plasmo) 🚀 Read more → 
文档Framework数据存储

存储 API

@plasmohq/storage 是来自 plasmo  的一个实用程序库,它抽象了浏览器扩展可用的持久存储 API。当扩展存储 API 不可用时,它会回退到 localStorage,允许在扩展页面、内容脚本、后台服务工作者和网页之间同步状态。

如果在 Plasmo 框架  项目中作为依赖项使用,此库将自动启用 storage 权限

安装

pnpm install @plasmohq/storage

该包导出以下模块,包括 ESM 和 CJS 格式:

模块描述
@plasmohq/storage基础 存储 API
@plasmohq/storage/secure安全存储 API
@plasmohq/storage/hookReact 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 时的更改:

background.ts
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

popup.tsx
const [hailingFrequency, setHailingFrequency] = useStorage("hailing", "42") ... <input value={hailingFrequency} onChange={(e) => setHailingFrequency(e.target.value) }/> // "42"

如果我们在 content.tsx 中订阅此键,我们将看到它为 undefined,直到使用定义的值调用 setHailingFrequency

content.tsx
const [hailingFrequency] = useStorage("hailing") return <p>{hailingFrequency}</p> // undefined

如果我们在 options.tsx 中订阅此键,但使用不同的静态初始值,我们将看到该值:

options.tsx
const [hailingFrequency] = useStorage("hailing", "147") return <p>{hailingFrequency}</p> // "147"

使用上述设置,假设我们在任何实例中调用 setHailingFrequency("8472"),我们将看到所有实例现在都显示 “8472”,并且现在将跟踪存储中的值而不是初始值。

渲染并持久化初始值

通过使用函数而不是静态值,初始值将被持久化在存储内存中。初始化函数有一个参数,即存储中的现有值。如果没有值,则为 undefined

假设我们有一个 popup.tsx,如果存储中没有任何内容,则将状态初始化为 “42”:

popup.tsx
const [hailingFrequency, setHailingFrequency] = useStorage("hailing", (v) => v === undefined ? "42": v) ... {hailingFrequency} // "42"

然后,如果我们在 content.tsxoptions.tsx 中创建一个新的 hook 实例,我们将看到持久化的初始值,而无需调用 setHailingFrequency

content.tsx
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 不能用于多个扩展(两个清单版本)。

最后更新于