跳到内容

useStorage

分类
导出大小
1.78 kB
最近更改
5 天前
相关

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

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

演示

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

用法

提示

当与 Nuxt 3 一起使用时,此函数将不会自动导入,而是优先使用 Nitro 内置的 useStorage()。 如果你想使用 VueUse 的函数,请显式导入。

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

// bind object
const state = useStorage('my-store', { hello: 'hi', greeting: 'Hello' })

// bind boolean
const flag = useStorage('my-flag', true) // returns Ref<boolean>

// bind number
const count = useStorage('my-count', 0) // returns Ref<number>

// bind string with SessionStorage
const id = useStorage('my-id', 'some-string-id', sessionStorage) // returns Ref<string>
// delete data from storage
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, since the value is not presented in storage

为了解决这个问题,你可以启用 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', from storage
console.log(state.value.greeting) // 'hello', from merged default value
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', from storage
console.log(state.value.greeting) // 'hello', from merged default value

当设置为 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 {
  /**
   * Watch for deep changes
   *
   * @default true
   */
  deep?: boolean
  /**
   * Listen to storage changes, useful for multiple tabs application
   *
   * @default true
   */
  listenToStorageChanges?: boolean
  /**
   * Write the default value to the storage when it does not exist
   *
   * @default true
   */
  writeDefaults?: boolean
  /**
   * Merge the default value with the value read from the storage.
   *
   * When setting it to true, it will perform a **shallow merge** for objects.
   * You can pass a function to perform custom merge (e.g. deep merge), for example:
   *
   * @default false
   */
  mergeDefaults?: boolean | ((storageValue: T, defaults: T) => T)
  /**
   * Custom data serialization
   */
  serializer?: Serializer<T>
  /**
   * On error callback
   *
   * Default log error to `console.error`
   */
  onError?: (error: unknown) => void
  /**
   * Use shallow ref as reference
   *
   * @default false
   */
  shallow?: boolean
  /**
   * Wait for the component to be mounted before reading the storage.
   *
   * @default false
   */
  initOnMounted?: boolean
}
export declare function useStorage(
  key: MaybeRefOrGetter<string>,
  defaults: MaybeRefOrGetter<string>,
  storage?: StorageLike,
  options?: UseStorageOptions<string>,
): RemovableRef<string>
export declare function useStorage(
  key: MaybeRefOrGetter<string>,
  defaults: MaybeRefOrGetter<boolean>,
  storage?: StorageLike,
  options?: UseStorageOptions<boolean>,
): RemovableRef<boolean>
export declare function useStorage(
  key: MaybeRefOrGetter<string>,
  defaults: MaybeRefOrGetter<number>,
  storage?: StorageLike,
  options?: UseStorageOptions<number>,
): RemovableRef<number>
export declare function useStorage<T>(
  key: MaybeRefOrGetter<string>,
  defaults: MaybeRefOrGetter<T>,
  storage?: StorageLike,
  options?: UseStorageOptions<T>,
): RemovableRef<T>
export declare function useStorage<T = unknown>(
  key: MaybeRefOrGetter<string>,
  defaults: MaybeRefOrGetter<null>,
  storage?: StorageLike,
  options?: UseStorageOptions<T>,
): RemovableRef<T>

源代码

SourceDemoDocs

贡献者

Anthony Fu
Fernando Fernández
Anthony Fu
IlyaL
sun0day
Jelf
Jeffrey Li
Robin
Yauheni Vasiukevich
OrbisK
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

更新日志

v12.8.0 on 3/5/2025
7432f - feat(types): deprecate `MaybeRef` and `MaybeRefOrGetter` in favor of Vue's native (#4636)
v12.4.0 on 1/10/2025
eb679 - feat: make storage key reactive (#4464)
dd316 - feat: use passive event handlers everywhere is possible (#4477)
v12.3.0 on 1/2/2025
59f75 - feat(toValue): deprecate `toValue` from @vueuse/shared in favor of Vue's native
v12.0.0-beta.1 on 11/21/2024
0a9ed - feat!: drop Vue 2 support, optimize bundles and clean up (#4349)
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)

在 MIT 许可证下发布。