Skip to content

useStorage

Category
Export Size
1.99 kB
Last Changed
15 minutes ago
Related

创建一个响应式引用,用于访问和修改 LocalStorageSessionStorage

默认情况下使用 localStorage,其他存储源可以通过第三个参数指定。

Demo

name: 'Banana'
color: 'Yellow'
size: 'Medium'
count: 0

用法

TIP

在使用 Nuxt 3 时,此函数将不会自动导入,而是使用 Nitro 内置的 useStorage()。如果要从 VueUse 使用该函数,请显式导入。

js
import { useStorage } from '@vueuse/core'

// 绑定对象
const state = useStorage('my-store', { hello: 'hi', greeting: 'Hello' })

// 绑定布尔值
const flag = useStorage('my-flag', true) // 返回 Ref<boolean>

// 绑定数字
const count = useStorage('my-count', 0) // 返回 Ref<number>

// 使用 SessionStorage 绑定字符串
const id = useStorage('my-id', 'some-string-id', sessionStorage) // 返回 Ref<string>

// 从存储中删除数据
state.value = null

合并默认值

默认情况下,useStorage 将使用存储中的值(如果存在)并忽略默认值。请注意,当您向默认值添加更多属性时,如果客户端的存储中没有该键,则该键可能是 undefined

ts
localStorage.setItem('my-store', '{"hello": "hello"}')

const state = useStorage('my-store', { hello: 'hi', greeting: 'hello' }, localStorage)

console.log(state.value.greeting) // undefined,因为存储中没有该值

为了解决这个问题,您可以启用 mergeDefaults 选项。

ts
localStorage.setItem('my-store', '{"hello": "nihao"}')

const state = useStorage(
  'my-store',
  { hello: 'hi', greeting: 'hello' },
  localStorage,
  { mergeDefaults: true } // <--
)

console.log(state.value.hello) // 'nihao',来自存储
console.log(state.value.greeting) // 'hello',来自合并的默认值
js
localStorage.setItem('my-store', '{"hello": "nihao"}')
const state = useStorage(
  'my-store',
  { hello: 'hi', greeting: 'hello' },
  localStorage,
  { mergeDefaults: true },
)
console.log(state.value.hello) // 'nihao',来自存储
console.log(state.value.greeting) // 'hello',来自合并的默认值

当设置为 true 时,它将对对象执行 浅合并。您可以传递一个函数来执行自定义合并(例如,深合并),例如:

ts
const state = useStorage(
  'my-store',
  { hello: 'hi', greeting: 'hello' },
  localStorage,
  { mergeDefaults: (storageValue, defaults) => deepMerge(defaults, storageValue) } // <--
)
js
const state = useStorage(
  'my-store',
  { hello: 'hi', greeting: 'hello' },
  localStorage,
  {
    mergeDefaults: (storageValue, defaults) =>
      deepMerge(defaults, storageValue),
  },
)

自定义序列化

默认情况下,useStorage 将根据提供的默认值的数据类型智能地使用相应的序列化程序。例如,对于对象,将使用 JSON.stringify / JSON.parse,对于数字,将使用 Number.toString / parseFloat,等等。

您也可以为 useStorage 提供自己的序列化函数:

ts
import { useStorage } from '@vueuse/core'

useStorage(
  'key',
  {},
  undefined,
  {
    serializer: {
      read: (v: any) => v ? JSON.parse(v) : null,
      write: (v: any) => JSON.stringify(v),
    },
  },
)
js
import { useStorage } from '@vueuse/core'
useStorage('key', {}, undefined, {
  serializer: {
    read: (v) => (v ? JSON.parse(v) : null),
    write: (v) => JSON.stringify(v),
  },
})

请注意,当您提供 null 作为默认值时,useStorage 无法从中推断出数据类型。在这种情况下,您可以提供自定义序列化程序或显式重用内置的序列化程序。

ts
import { StorageSerializers, useStorage } from '@vueuse/core'

const objectLike = useStorage('key', null, undefined, { serializer: StorageSerializers.object })
objectLike.value = { foo: 'bar' }

类型声明

显示类型声明
typescript
export interface Serializer<T> {
  read: (raw: string) => T
  write: (value: T) => string
}
export interface SerializerAsync<T> {
  read: (raw: string) => Awaitable<T>
  write: (value: T) => Awaitable<string>
}
export declare const StorageSerializers: Record<
  "boolean" | "object" | "number" | "any" | "string" | "map" | "set" | "date",
  Serializer<any>
>
export declare const customStorageEventName = "vueuse-storage"
export interface StorageEventLike {
  storageArea: StorageLike | null
  key: StorageEvent["key"]
  oldValue: StorageEvent["oldValue"]
  newValue: StorageEvent["newValue"]
}
export interface UseStorageOptions<T>
  extends ConfigurableEventFilter,
    ConfigurableWindow,
    ConfigurableFlush {
  /**
   * 监听深层次的变化
   *
   * @default true
   */
  deep?: boolean
  /**
   * 监听存储变化,适用于多标签页应用程序
   *
   * @default true
   */
  listenToStorageChanges?: boolean
  /**
   * 当存储中不存在时,将默认值写入存储
   *
   * @default true
   */
  writeDefaults?: boolean
  /**
   * 将默认值与从存储中读取的值合并。
   *
   * 当设置为 true 时,它将对对象执行 **浅层合并**。
   * 您可以传递一个函数来执行自定义合并(例如,深层合并),例如:
   *
   * @default false
   */
  mergeDefaults?: boolean | ((storageValue: T, defaults: T) => T)
  /**
   * 自定义数据序列化
   */
  serializer?: Serializer<T>
  /**
   * 错误回调
   *
   * 默认将错误记录到 `console.error`
   */
  onError?: (error: unknown) => void
  /**
   * 将浅层 ref 用作引用
   *
   * @default false
   */
  shallow?: boolean
  /**
   * 在组件挂载后再读取存储
   *
   * @default false
   */
  initOnMounted?: boolean
}
export declare function useStorage(
  key: string,
  defaults: MaybeRefOrGetter<string>,
  storage?: StorageLike,
  options?: UseStorageOptions<string>,
): RemovableRef<string>
export declare function useStorage(
  key: string,
  defaults: MaybeRefOrGetter<boolean>,
  storage?: StorageLike,
  options?: UseStorageOptions<boolean>,
): RemovableRef<boolean>
export declare function useStorage(
  key: string,
  defaults: MaybeRefOrGetter<number>,
  storage?: StorageLike,
  options?: UseStorageOptions<number>,
): RemovableRef<number>
export declare function useStorage<T>(
  key: string,
  defaults: MaybeRefOrGetter<T>,
  storage?: StorageLike,
  options?: UseStorageOptions<T>,
): RemovableRef<T>
export declare function useStorage<T = unknown>(
  key: string,
  defaults: MaybeRefOrGetter<null>,
  storage?: StorageLike,
  options?: UseStorageOptions<T>,
): RemovableRef<T>

Source

SourceDemoDocs

贡献者

Anthony Fu
丶远方
Fernando Fernández
sun0day
Jelf
Jeffrey Li
Anthony Fu
Callum Macrae
Isaac Qadri
Matt Sanders
Doctorwu
Eduardo San Martin Morote
Daniel Maixner
chenglu
David Ma
Daniel Mittereder
Clément Ollivier
James Garbutt
Yury Rudey
Puru Vijay
webfansplz
spking11
Maurici Abad Gutierrez
Guillaume Chau
Denis Blazhkun
Andreas Weber
Le Minh Tri
Jamie Warburton
Shinigami
Sasan Farrokh
Pig Fang
wheat
Alex Kozack
Nurettin Kaya
Pine
Antério Vieira
Ivan Demchuk

变更日志

v11.0.1 on 8/19/2024
a9b49 - fix: sync within the same document (#4152)
v11.0.0-beta.2 on 7/17/2024
5a302 - feat: conditionally use event based on the used storage backend (#3822)
v10.8.0 on 2/20/2024
f7ea1 - fix: ensure setting value to null syncs to other instances (#3737)
a086e - fix: stricter types
v10.7.0 on 12/5/2023
04220 - fix: fix undefined defaults (#3597)
v10.6.0 on 11/9/2023
dc6f2 - feat: add waitOnMounted option for SSR (#3504)
b6d2b - fix: fix defaults not unwrapped (#3534)
v10.4.0 on 8/25/2023
6fabe - fix: read object only when it's serialized differently (#2782) (#3091)
v10.0.0-beta.5 on 4/13/2023
cb644 - refactor!: remove isFunction and isString utils
v10.0.0-beta.4 on 4/13/2023
4d757 - feat(types)!: rename MaybeComputedRef to MaybeRefOrGetter
0a72b - feat(toValue): rename resolveUnref to toValue
v9.13.0 on 2/18/2023
c6185 - fix: emit a custom event to support custom storage areas (#2630)
v9.8.2 on 12/20/2022
800f7 - fix: sync within page, close #1595
v9.8.1 on 12/20/2022
c3851 - fix: resume the watch after setting the value, fix loop updates

Released under the MIT License.