$, они не требуют импорта, так как являются неотъемлемой частьюРуна
$state() используется для создания реактивного состояния, которое автоматически обновляет интерфейс при изменении данных.Допустим, нам нужно получить список задач и отобразить его.
<script>Если мы используем в
import { onMount } from 'svelte';
let todos = $state([]); // создаем реактивное состояние
// асинхронно запрашиваем из сервера список задач
async function getAllTodos() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/todos');
if (!response.ok) {
throw new Error(`Статус ошибки: ${response.status}`);
}
todos = await response.json();
} catch (error) {
console.error(error.message);
}
}
// при монтировании компонента делаем запрос
onMount(async () => {
await getAllTodos();
});
</script>
<!-- Проверка, что пришел точно массив и в нем есть элементы -->
{#if Array.isArray(todos) && todos.length > 0}
<ul>
<!-- Проходим по массиву и выводим -->
{#each todos as todo}
<li>
<span>{todo.title}</span>
<input type="checkbox" checked={todo.completed} />
</li>
{/each}
</ul>
{/if}
$state массив или объект, то результатом становится прокси — объект в JavaScript, который перехватывает операции с данными и добавляет к ним свою логику. Это позволяет Svelte отслеживать изменения в массивах и объектах на любом уровне вложенности. Важно, что такие данные можно мутировать, например, с помощью метода .push(), при этом оригинальные данные не будут изменены благодаря работе прокси.Однако бывают случаи, когда нам не обязательно нужна глубокая реактивность. Например, если мы динамически подгружаем диаграммы или список публикаций в ленте, для этого может пригодиться руна
$state.raw, которая предотвращает прямую мутацию состояния. Это полезно, если нам нужно управлять состоянием вручную и избежать перехватов операций на уровне вложенных данных.Предположим, что при монтировании списка задач мы хотим изменить заголовок первого элемента массива. Для примера рассмотрим два варианта — с использованием
$state([]) и $state.raw([]):let todos = $state.raw([]);Иногда нам необходимо отслеживать изменения в массиве или объекте и для этого подойдет руна
// let todos = $state([]); // если бы использовали обычное $state
...
onMount(async() => {
await getAllTodos();
// При $state([]) следующая строка сработает напрямую:
// todos[0].title = 'hello first string';
// Но при $state.raw([]) нужно обновить массив целиком:
todos = todos.map((todo, index) =>
index === 0
? { ...todo, title: 'hello first string' }
: todo
);
});
$state.snapshot. Дело в том, что если мы попробуем просто вывести реактивное состояние в консоль, Svelte сразу предупредит нас об этом:let todos = $state([]);Используя
...
onMount(async() => {
await getAllTodos();
// Warning: Your `console.log` contained `$state` proxies. Consider using `$inspect(...)` or `$state.snapshot(...)` instead
// console.log(todos);
console.log($state.snapshot(todos));
});
$state.snapshot, мы получаем статичный снимок текущего состояния, который больше не является реактивным. Это полезно, если нам нужно просто посмотреть на данные без отслеживания последующих изменений.Также в процессе разработки можно использовать
$inspect, которая запускается каждый раз при изменении отслеживаемого состояния. Она работает исключительно в режиме разработки и полностью исчезает после сборки. В отличие от обычного console.log, руна $inspect автоматически обновляется и логирует новые значения при каждом изменении данных:let todos = $state([]);Важно помнить, что
...
onMount(async() => {
await getAllTodos();
});
$inspect(todos);
$inspect предоставляет возможность следить за изменениями реактивного состояния в реальном времени, что может быть крайне полезно при отладке