Skip to content

Реактивное хранилище

useStorage() — базовый composable. Работает с localStorage, sessionStorage и in-memory запасным вариантом.

ts
useStorage<T>(key: string, options: StorageOptions<T>): UseStorageReturn<T>

Опции

defaultValue

T

Значение, возвращаемое, когда ключ отсутствует или истёк.

target

'local' | 'session' | 'memory' | 'indexeddb' · по умолчанию: 'local'

Backend хранилища. 'indexeddb' хранит через единственное выделенное object store (БД vue-storage-kit, store kv) — для собственных баз/store или вторичных индексов используйте useIndexedDB() / useIDBRef().

ttl

number

Время жизни в миллисекундах; 0 или не задано = без истечения.

version

number · по умолчанию: 1

Версия схемы сохранённых данных.

migrations

Migration[] · по умолчанию: []

Функции миграции, запускаемые при несовпадении сохранённой версии с version — см. Миграции схемы.

encrypt

boolean | EncryptOptions · по умолчанию: false

Включить AES-GCM шифрование — см. Шифрование.

compress

boolean | CompressOptions · по умолчанию: false

Сжимать сохранённый конверт через Compression Streams API. Применяется до encrypt, так что сжатие всё ещё работает на открытом тексте (сжатый шифротекст не даёт выигрыша в размере) — см. Сжатие.

sign

boolean | SignOptions · по умолчанию: false

Проверка HMAC-SHA256, применяется как самый внешний слой (оборачивает и сжатые/зашифрованные данные тоже). Обнаруживает случайное повреждение без требования секретности — не защита от пользователя, редактирующего собственное хранилище — см. Обнаружение повреждения — комбинируйте с encrypt для обоих.

sync

boolean | SyncOptions · по умолчанию: false

Включить синхронизацию между вкладками через BroadcastChannel — см. Синхронизация вкладок.

debounce

number

Объединяет записи: сохраняет только через debounce мс после последнего изменения. Взаимоисключающе с throttle (при обоих заданных побеждает throttle).

throttle

number

Писать не чаще раза в throttle мс даже при непрерывных изменениях, вместо ожидания их остановки.

history

number

Хранить в памяти до этого числа прошлых значений для undo()/redo(). Не сохраняется — сбрасывается при перезагрузке.

evictOnQuota

boolean | { max?: number } · по умолчанию: false

При QuotaExceededError, если зачистки истёкших по TTL записей этого адаптера недостаточно, вытесняет его наименее недавно записанные другие ключи (сначала самые старые, до max, по умолчанию 1) и повторяет попытку. Выключено по умолчанию — удаление несвязанных ключей это реальный побочный эффект.

serializer

Serializer<T> · по умолчанию: JSON-сериализатор

Кастомная пара сериализации/десериализации.

onError

(err: StorageError) => void

Вызывается вместо выброса исключения при превышении квоты, ошибках парсинга, ошибках криптографии, неверных подписях или других сбоях записи.

onExpire

(key: string) => void

Вызывается, когда истёкший по TTL ключ удаляется при чтении.

onMigrate

(from: number, to: number) => void

Вызывается после успешной миграции.

Возвращаемое значение

value

Ref<T>

Реактивная двусторонняя привязка; присваивание пишет в хранилище.

isReady

Ref<boolean>

false, пока не завершится первичное асинхронное чтение (важно для IndexedDB и зашифрованных значений).

error

Ref<StorageError | null>

Последняя ошибка, null, если её нет.

expiry

ComputedRef<Date | null>

Когда ключ истекает, null, если TTL не задан.

canUndo

ComputedRef<boolean>

Есть ли эффект от undo() прямо сейчас (всегда false, если history не задан).

canRedo

ComputedRef<boolean>

Есть ли эффект от redo() прямо сейчас (всегда false, если history не задан).

remove

() => void

Удалить ключ из хранилища и сбросить value к defaultValue.

refresh

() => Promise<void>

Перечитать из хранилища (полезно, если другой процесс мог записать).

undo

() => void

Перемещение назад по значениям, записанным через history; no-op, если history не задан или стек undo пуст.

redo

() => void

Перемещение вперёд по значениям, записанным через history; no-op, если history не задан или стек redo пуст.

Примеры

Базовое чтение/запись:

ts
const { value: counter } = useStorage('counter', { defaultValue: 0 })

counter.value++ // немедленно пишет в localStorage

Session storage:

ts
const { value: token } = useStorage('auth-token', {
  defaultValue: '',
  target: 'session',
})

TTL — автоматическое истечение через 30 минут:

ts
const { value: cache, expiry } = useStorage('search-cache', {
  defaultValue: [] as string[],
  ttl: 30 * 60 * 1000,
  onExpire: (key) => console.log(`${key} expired`),
})

console.log(expiry.value) // Date | null

Обработка ошибок:

ts
const { value, error } = useStorage('data', {
  defaultValue: {},
  onError: (err) => {
    if (err.type === 'quota-exceeded') showToast('Storage is full')
    if (err.type === 'parse-error') console.warn('Corrupted value, reset to default')
  },
})

Кастомный сериализатор:

ts
import type { Serializer } from 'vue-storage-kit'

const base64Serializer: Serializer<string> = {
  serialize: (v) => btoa(v),
  deserialize: (raw) => atob(raw),
}

const { value } = useStorage('encoded', {
  defaultValue: '',
  serializer: base64Serializer,
})

useLocalStorage / useSessionStorage

Сокращённые composables — идентичны useStorage, но с предустановленным target и defaultValue в качестве второго аргумента (сигнатура, совместимая с vueuse).

ts
useLocalStorage<T>(key: string, defaultValue: T, opts?): UseStorageReturn<T>
useSessionStorage<T>(key: string, defaultValue: T, opts?): UseStorageReturn<T>
ts
import { useLocalStorage, useSessionStorage } from 'vue-storage-kit'

const { value: settings } = useLocalStorage('settings', { theme: 'light', lang: 'en' })
const { value: draft } = useSessionStorage('draft', '')

Это прямые замены useLocalStorage / useSessionStorage из @vueuse/core.

defineStorageKey

Типизированный переиспользуемый дескриптор ключа — определите форму ключа и его опции один раз, а затем передавайте дескриптор напрямую в useStorage(), вместо того чтобы повторять key/options в каждом месте вызова.

ts
function defineStorageKey<T>(key: string, options: StorageOptions<T>): StorageKeyDef<T>

useStorage() принимает как обычную пару (key, options), так и одиночный StorageKeyDef<T>:

ts
useStorage<T>(key: string, options: StorageOptions<T>): UseStorageReturn<T>
useStorage<T>(def: StorageKeyDef<T>): UseStorageReturn<T>
ts
import { defineStorageKey, useStorage } from 'vue-storage-kit'

// Определяем один раз, например в общем модуле keys.ts
const themeKey = defineStorageKey('theme', {
  defaultValue: 'light' as 'light' | 'dark',
  ttl: undefined,
})

// Используем где угодно, полностью типизировано, без повторения опций
const { value: theme } = useStorage(themeKey)