В Svelte управление состоянием строится вокруг реактивной модели, где изменения данных автоматически отражаются в интерфейсе без необходимости вручную вызывать обновления. Помимо локального состояния компонентов, фреймворк предоставляет отдельный механизм — stores, предназначенный для разделения и масштабирования состояния между компонентами и модулями приложения.
Stores представляют собой объекты с подписочной моделью, реализующие паттерн наблюдателя. Основная идея заключается в том, что состояние хранится вне компонентов, а доступ к нему осуществляется через единый интерфейс подписки.
Store в Svelte — это объект, который реализует минимальный контракт:
subscribeset и update (в случае
writable store)const store = {
subscribe: (callback) => {
callback(value);
return () => {};
}
};
Любой объект, соответствующий этому интерфейсу, может использоваться как store.
Ключевая особенность: Svelte не требует наследования или специального класса. Достаточно соблюдать контракт подписки.
Наиболее часто используемый тип store — writable store, позволяющий изменять значение извне.
Создание осуществляется через функцию writable:
import { writable } from 'svelte/store';
const count = writable(0);
set(value) — полная замена значенияupd ate(fn) — обновление на основе текущего
состоянияsubscribe(fn) — реактивное чтение значенияПример:
count.se t(10);
count.update(n => n + 1);
Подписка — фундаментальный механизм работы store.
const unsubscribe = count.subscribe(value => {
console.log(value);
});
Подписка:
unsubscribe();
Этот механизм позволяет интегрировать store с любыми внешними системами: WebSocket, DOM API, сторонними библиотеками.
Svelte предоставляет синтаксический сахар — автоматическую подписку
через $.
<script>
import { count } from './store.js';
</script>
<h1>{$count}</h1>
<button on:click={() => count.update(n => n + 1)}>
Increment
</button>
Особенности:
$count автоматически подписывается на storeЭтот механизм делает store прозрачным внутри UI-логики.
Readable store используется, когда состояние не должно изменяться извне.
import { readable } from 'svelte/store';
const time = readable(new Date(), set => {
const interval = setInterval(() => {
set(new Date());
}, 1000);
return () => clearInterval(interval);
});
setМеханизм cleanup-функции важен: он освобождает ресурсы при отсутствии подписчиков.
Derived store позволяет строить новое состояние на основе других stores.
import { derived } from 'svelte/store';
const doubled = derived(count, $count => $count * 2);
const sum = derived(
[a, b],
([$a, $b]) => $a + $b
);
const user = derived(id, ($id, set) => {
fetch(`/api/user/${$id}`)
.then(r => r.json())
.then(set);
return () => {};
});
Derived stores:
Любой объект с методом subscribe может быть store. Это
позволяет создавать собственные абстракции.
function createCounter() {
const { subscribe, set, upd ate } = writable(0);
return {
subscribe,
increment: () => upd ate(n => n + 1),
decrement: () => upd ate(n => n - 1),
reset: () => se t(0)
};
}
export const counter = createCounter();
Преимущества:
Stores в Svelte часто используются как глобальные модули состояния.
Пример структуры:
src/
stores/
auth.js
cart.js
settings.js
import { writable } from 'svelte/store';
export const user = writable(null);
export const login = (data) => {
user.se t(data);
};
export const logout = () => {
user.se t(null);
};
Такой подход позволяет:
Svelte компилирует $store в подписку и локальную
переменную.
$: doubled = $count * 2;
Store и реактивные выражения часто комбинируются:
$store — реактивное значение$: — реактивные вычисленияStores реализуют однонаправленный поток данных:
set или
updateЗапрещается:
setStores часто используются как адаптер между Svelte и внешними API.
import { writable } from 'svelte/store';
export function createSocketStore(url) {
const { subscribe, set } = writable(null);
const socket = new WebSocket(url);
socket.onmess age = (event) => {
set(JSON.parse(event.data));
};
return { subscribe };
}
Stores в Svelte оптимизированы под минимальные издержки:
Однако возможны проблемы:
set могут вызывать лишние обновления UIStores часто заменяют глобальный state management, но не всегда являются полной альтернативой сложным решениям вроде Redux.
Сильные стороны:
Слабые стороны:
Stores можно комбинировать для построения сложных систем состояния.
const firstName = writable('John');
const lastName = writable('Doe');
const fullName = derived(
[firstName, lastName],
([$firstName, $lastName]) => `${$firstName} ${$lastName}`
);
Композиция:
В реальных приложениях stores выполняют роль:
Типичная архитектура:
$storeНа практике часто встречаются проблемы:
Локальное состояние:
Stores:
Выбор зависит от области применения данных, а не от их типа.