Compound stores — это расширение стандартной концепции
stores в SvelteKit, позволяющее объединять несколько
реактивных состояний в одну логическую единицу. В отличие от обычного
writable или readable store, compound store
предоставляет структуру для работы с комплексными данными, сохраняя
реактивность и облегчая управление состоянием на уровне нескольких
связанных значений.
Ключевая особенность — агрегация нескольких под-stores и возможность централизованного управления ими через единый интерфейс.
Для создания compound store можно использовать комбинацию стандартных
writable и derived store. Основная идея —
инкапсулировать логику работы с несколькими store в одном объекте:
import { writable, derived } from 'svelte/store';
function createUserStore() {
const name = writable('');
const age = writable(0);
const isAdult = derived(age, $age => $age >= 18);
return {
name,
age,
isAdult,
setName: (newName) => name.set(newName),
setAge: (newAge) => age.set(newAge),
reset: () => {
name.set('');
age.set(0);
}
};
}
export const userStore = createUserStore();
Разбор:
name и age — базовые writable
stores.isAdult — derived store, который
автоматически пересчитывается при изменении age.setName, setAge и
reset инкапсулируют логику управления состоянием, сохраняя
интерфейс store чистым и предсказуемым.Compound store поддерживает привычную подписку через
subscribe, но для комплексных объектов рекомендуется
подписываться на отдельные свойства или использовать комбинированные
подписки:
$userStore.name; // доступ к значению name
$userStore.isAdult.subscribe(value => {
console.log('Пользователь совершеннолетний:', value);
});
Можно также подписываться на весь compound store через вспомогательную функцию:
import { derived } from 'svelte/store';
const userData = derived(
[userStore.name, userStore.age],
([$name, $age]) => ({ name: $name, age: $age })
);
userData.subscribe(data => console.log(data));
Такой подход полезен, когда нужно получить сразу агрегированные данные, не подписываясь на каждое поле по отдельности.
Compound stores особенно эффективны при работе с объектами и массивами, где требуется поддержка реактивности на вложенных уровнях. Пример — управление списком задач:
function createTodoStore() {
const todos = writable([]);
const addTodo = (text) => {
todos.update(current => [...current, { text, done: false }]);
};
const toggleTodo = (index) => {
todos.update(current =>
current.map((todo, i) =>
i === index ? { ...todo, done: !todo.done } : todo
)
);
};
const removeTodo = (index) => {
todos.update(current => current.filter((_, i) => i !== index));
};
const completedCount = derived(todos, $todos =>
$todos.filter(todo => todo.done).length
);
return {
todos,
addTodo,
toggleTodo,
removeTodo,
completedCount
};
}
export const todoStore = createTodoStore();
Особенности:
derived свойствах.Compound store легко интегрируется в компоненты:
<script>
import { todoStore } from './stores.js';
let newTodo = '';
</script>
<input bind:value={newTodo} placeholder="Добавить задачу" />
<button on:click={() => { todoStore.addTodo(newTodo); newTodo = ''; }}>
Добавить
</button>
<ul>
{#each $todoStore.todos as todo, index}
<li>
<input type="checkbox" bind:checked={todo.done} on:change={() => todoStore.toggleTodo(index)} />
{todo.text}
<button on:click={() => todoStore.removeTodo(index)}>Удалить</button>
</li>
{/each}
</ul>
<p>Выполнено: {$todoStore.completedCount}</p>
Преимущества:
Инкапсуляция Всегда предоставлять публичный
интерфейс для управления состоянием через методы. Не раскрывать
внутренние writable без необходимости.
Разделение логики Для сложных объектов разбивать
store на под-store и объединять через derived или
вспомогательные функции.
Оптимизация производительности Минимизировать
подписки на массивы и объекты целиком, использовать derived
для вычислений и агрегатов.
Тестируемость Compound store легко тестировать вне компонентов Svelte, что повышает надежность приложения.
Согласованность реактивности Вложенные объекты
должны обновляться через update или создание новых копий
(spread operator), чтобы сохранялась реактивность
Svelte.
Compound stores обеспечивают структурированное и реактивное управление сложными состояниями, делая SvelteKit приложения более масштабируемыми, удобными в сопровождении и тестируемыми.