Skip to content

WXT 存储

更新日志

更新日志

一个简化扩展存储接口的封装。

安装

使用 WXT

该模块内置在 WXT 中,因此无需额外安装。

typescript
import { storage } from 'wxt/storage';

如果使用自动生成的导入,storage 会自动导入,因此无需甚至需要导入!

不使用 WXT

通过 npm 包装:

bash
npm i @wxt-dev/storage
pnpm add @wxt-dev/storage
yarn add @wxt-dev/storage
bun add @wxt-dev/storage
typescript
import { storage } from '@wxt-dev/storage';

存储权限

要使用 wxt/storage API,必须在配置中添加 "storage" 权限:

typescript
// wxt.config.ts
export default defineConfig({
  manifest: {
    permissions: ['storage'],
  },
});

基本用法

所有存储键都必须以存储区域前缀。

typescript
// ❌ 这会抛出错误
await storage.getItem('installDate');

// ✅ 这是好的
await storage.getItem('local:installDate');

你可以使用 local:, session:, sync:, 或 `managed:``。如果你使用 TypeScript,可以在大多数方法上添加类型参数来指定键值的预期类型:

typescript
await storage.getItem<number>('local:installDate');
await storage.watch<number>(
  'local:installDate',
  (newInstallDate, oldInstallDate) => {
    // ...
  },
);
await storage.getMeta<{ v: number }>('local:installDate');

要查看可用的所有方法,请参阅 API 参考.

监听变化

要监听存储变化,使用 storage.watch 函数。它让你可以设置一个监听器来为单个键:

typescript
const unwatch = storage.watch<number>('local:counter', (newCount, oldCount) => {
  console.log('计数已改变:', { newCount, oldCount });
});

要移除监听器,调用返回的 unwatch 函数:

typescript
const unwatch = storage.watch(...);

// 一些时间后...
unwatch();

度量

wxt/storage 还支持为键设置度量,存储在 key + "$". 度量是一个由键相关属性集合组成的对象。它可以是版本号、最后修改日期等。

除了版本化,你负责管理一个字段的度量:

typescript
await Promise.all([
  storage.setItem('local:preference', true),
  storage.setMeta('local:preference', { lastModified: Date.now() }),
]);

当你从多个调用中设置不同属性时,这些属性会合并而不是被覆盖:

typescript
await storage.setMeta('local:preference', { lastModified: Date.now() });
await storage.setMeta('local:preference', { v: 2 });

await storage.getMeta('local:preference'); // { v: 2, lastModified: 1703690746007 }

你可以移除所有与键相关的度量,或仅特定属性:

typescript
// 移除所有属性
await storage.removeMeta('local:preference');

// 移除仅 `"lastModified"` 属性
await storage.removeMeta('local:preference', 'lastModified');

// 移除多个属性
await storage.removeMeta('local:preference', ['lastModified', 'v']);

定义存储项

写键和类型参数对所有存储键重复太多。作为替代,你可以使用 storage.defineItem 来创建一个“存储项”。

存储项包含与 storage 变量相同的 API,但你可以配置其类型、默认值和其他在一个地方:

typescript
// utils/storage.ts
const showChangelogOnUpdate = storage.defineItem<boolean>(
  'local:showChangelogOnUpdate',
  {
    fallback: true,
  },
);

现在,而不是使用存储变量,你可以使用你创建的存储项上的辅助函数:

typescript
await showChangelogOnUpdate.getValue();
await showChangelogOnUpdate.setValue(false);
await showChangelogOnUpdate.removeValue();
const unwatch = showChangelogOnUpdate.watch((newValue) => {
  // ...
});

对于可用的所有属性和方法,请参阅 API 参考.

版本化

如果你预计存储项会变化或增长,你可以为存储项添加版本控制。当你定义第一个版本的存储项时,从 1 开始。

考虑一个存储项,它存储被 WXT 忽略的网站列表:

typescript
export const ignoredWebsites = storage.defineItem<string[]>( 
'local:ignoredWebsites',
{
  fallback: [],
},
);
typescript
import { nanoid } from 'nanoid'; 

// 恢复并添加一个类型以反向兼容 v1
type IgnoredWebsiteV1 = string; 
interface IgnoredWebsiteV2 { 
  id: string; 
  website: string; 
} 

export const ignoredWebsites = storage.defineItem<string[]>( 
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( 
'local:ignoredWebsites',
{
  fallback: [],
  version: 2, 
  migrations: { 
    // 迁移到 v1 到 v2
    2: (websites: IgnoredWebsiteV1[]): IgnoredWebsiteV2[] => {
      return websites.map((website) => ({ id: nanoid(), website }));
    }, 
  },
},
);

迁移

一旦 storage.defineItem 被调用,WXT 会检查是否需要运行迁移,并如果需要则运行它们。读取或写入存储项值(例如 getValue, setValue, removeValue, getMeta, 等等)将自动等待迁移过程完成,然后再实际读取或写入值。

默认值

使用 storage.defineItem 有多种方式定义默认值:

  1. fallback - 如果值缺失,则返回此值而不是 null

    这对提供默认值的设置非常有用:

    typescript
    const theme = storage.defineItem('local:theme', {
      fallback: 'dark',
    });
    const allowEditing = storage.defineItem('local:allow-editing', {
      fallback: true,
    });
  2. init - 初始化并保存到存储如果尚未保存。

    这对需要初始化或只在一次时设置的值非常有用:

    typescript
    const userId = storage.defineItem('local:user-id', {
      init: () => globalThis.crypto.randomUUID(),
    });
    const installDate = storage.defineItem('local:install-date', {
      init: () => new Date().getTime(),
    });

    值在存储中立即初始化。

批处理操作

获取或设置多个存储值时,你可以执行批处理操作以提高性能。storage API 提供了进行批量操作的方法:

  • getItems - 获取多个值。
  • getMetas - 获取多个项的度量。
  • setItems - 设置多个值。
  • setMetas - 设置多个项的度量。
  • removeItems - 移除多个值(并可选地移除度量)。

所有这些 API 支持字符串键和定义的存储项:

typescript
const userId = storage.defineItem('local:userId');

await storage.setItems([
  { key: 'local:installDate', value: Date.now() },
  { item: userId, value: generateUserId() },
]);

有关更多类型和示例,请参阅 API 参考.