Сторы
Стор хранит значение модели. Если приложению нужно что-то помнить между событиями, это почти всегда стор: текст поля, выбранный id, список сообщений, статус формы, кешированные данные.
const query = store("");
const profile = store({ name: "Ada", age: 36 });Стор не является глобальной переменной. Он описывает, какое значение существует в модели, а конкретное значение лежит в scope. Поэтому один и тот же стор может иметь разные значения в разных scopes.
const first = scope();
const second = scope();
scoped(first, () => {
query.value = "docs";
});
scoped(second, () => {
query.value = "api";
});В первом scope у query будет "docs", во втором — "api". Код модели при этом один и тот же.
Чтение и запись
Сторы с примитивными значениями читаются через .value.
count.value += 1;Сторы с объектами раскрывают поля напрямую.
profile.age += 1;Прямое чтение или запись требуют scope в текущем контексте выполнения. Если код не находится внутри реакции, effect handler или другой ветки, где scope уже известен, откройте его через scoped(scope, fn).
Derived-сторы
Derived-стор нужен, когда значение полностью следует из другого значения. Например, label поиска можно вычислить из query, а не обновлять вручную в каждой реакции.
const queryLabel = query.map((text) => (text ? `Searching: ${text}` : "Search"));Derived-сторы ленивые. Если на такой стор не подписана реакция или UI, изменение source-стора только помечает его кеш грязным. Пересчет произойдет позже, когда значение явно прочитают. Если derived-стор активен, например на него подписана реакция, изменение зависимостей сразу пересчитает значение и запустит подписчиков только при реальном изменении результата.
Если значение зависит от события во времени, это уже не derived-стор. Тогда лучше хранить обычный стор и менять его через реакцию.
Ленивые вычисления
computed нужен для значений, которые выводятся из состояния, но не должны пересчитываться до чтения. Это полезно для тяжелой фильтрации, сортировки, сборки view-model или правил, где зависимости удобнее определить по фактическим чтениям.
const query = store("");
const users = store({ items: [] as User[] });
const visibleUsers = computed(() => {
const text = query.value.toLowerCase();
return users.items.filter((user) => user.name.toLowerCase().includes(text));
});visibleUsers ведет себя как read-only стор. Первый read в scope выполнит функцию и запомнит результат. Следующие чтения вернут кеш. Когда query или users изменятся в этом же scope, кеш станет грязным, но значение не пересчитается, пока его снова не прочитают или пока его не наблюдает реакция, подписка или UI.
Обычный store() считается активным всегда: запись должна сохранить новое значение. Derived-сторы активируются только наблюдением. Используйте map, когда нужен простой derived-стор от одного источника. Используйте computed, когда вычисление дорогое, зависит от нескольких сторов или зависит от веток внутри самой функции.