Одной из основных особенностей Svelte является реактивность. Это концепция, при которой изменения данных автоматически отражаются в интерфейсе, без необходимости вручную обновлять DOM или использовать сторонние библиотеки для управления состоянием. В Svelte реактивность встроена на уровне языка, что упрощает разработку и повышает производительность.
Reaktivность в Svelte достигается через реактивные переменные. Эти переменные отслеживают изменения данных и автоматически обновляют связанные с ними части интерфейса. Пример базового использования:
<script>
let count = 0;
</script>
<button on:click={() => count += 1}>
Счётчик: {count}
</button>
В этом примере переменная count является реактивной.
Когда пользователь нажимает на кнопку, значение переменной изменяется, и
Svelte автоматически обновляет DOM, отображая новое значение
счётчика.
Svelte использует декларативный подход для описания реактивности.
Чтобы указать, что переменная или выражение должно быть реактивным,
достаточно использовать конструкцию $:, которая помечает
реактивное выражение. Пример:
<script>
let x = 5;
let y = 10;
$: sum = x + y;
</script>
<p>Сумма: {sum}</p>
Здесь переменная sum автоматически пересчитывается
каждый раз, когда изменяются значения x или y.
Оператор $: указывает, что выражение справа должно быть
реактивным, и при изменении значений переменных Svelte автоматически
пересчитает sum и обновит DOM.
Реактивные выражения могут быть не только простыми арифметическими операциями. В Svelte можно использовать более сложные вычисления и выражения, которые автоматически обновляются при изменении зависимых переменных. Это позволяет легко строить динамические интерфейсы.
<script>
let firstName = "Иван";
let lastName = "Иванов";
$: fullName = `${firstName} ${lastName}`;
</script>
<p>Полное имя: {fullName}</p>
В данном примере fullName будет автоматически
обновляться при изменении firstName или
lastName. Этот подход позволяет минимизировать
необходимость в дополнительных методах или событиях для отслеживания
изменений.
Реактивность в Svelte может быть использована не только в простых выражениях, но и в более сложных методах. Например, при взаимодействии с API, загрузке данных или фильтрации:
<script>
let searchTerm = '';
let items = ['Яблоки', 'Бананы', 'Груши', 'Апельсины'];
$: filteredItems = items.filter(item => item.includes(searchTerm));
</script>
<input type="text" bind:value={searchTerm} placeholder="Поиск...">
<ul>
{#each filteredItems as item}
<li>{item}</li>
{/each}
</ul>
Здесь, при каждом изменении значения searchTerm, Svelte
автоматически обновит список filteredItems, отфильтровав
элементы на основе введённого текста.
Для более сложных приложений в Svelte часто используется концепция
store (хранилища). Store позволяет управлять состоянием, которое может
быть доступно и изменяемо из разных частей приложения. В Svelte есть
несколько типов store, включая writable,
readable и derived.
Пример использования writable store:
<script>
import { writable } from 'svelte/store';
const count = writable(0);
</script>
<button on:click={() => $count += 1}>
Счётчик: {$count}
</button>
Здесь переменная count хранится в хранилище типа
writable. Хранилища могут быть реактивными, и, используя
$ перед названием store, можно автоматически отслеживать
изменения и обновлять интерфейс.
Svelte автоматически оптимизирует обновления при использовании реактивных переменных. В случае, если несколько реактивных переменных зависят друг от друга, Svelte старается минимизировать количество перерисовок интерфейса, обновляя только те части DOM, которые действительно изменились.
Кроме того, Svelte использует компиляцию для создания эффективного кода, который минимизирует лишние вычисления и обновления. Например, если переменная, которая не используется в шаблоне, изменяется, её обновление не вызовет перерасчёта DOM.
При работе с асинхронными данными важно учитывать, что Svelte будет корректно работать с реактивными переменными даже в случае загрузки данных с сервера. Пример:
<script>
let data = [];
let loading = true;
async function fetchData() {
const response = await fetch('https://api.example.com/data');
data = await response.json();
loading = false;
}
fetchData();
</script>
{#if loading}
<p>Загрузка...</p>
{:else}
<ul>
{#each data as item}
<li>{item.name}</li>
{/each}
</ul>
{/if}
Здесь при изменении состояния переменной data или
loading Svelte автоматически обновит DOM, отображая либо
индикатор загрузки, либо саму информацию.
С момента появления реактивных переменных в Svelte разработчики
столкнулись с понятием “референсного типа данных”. Важно понимать, что
при изменении сложных объектов, таких как массивы или объекты, Svelte
отслеживает изменения на уровне ссылки, а не содержимого объекта. Чтобы
гарантировать реактивность при изменении содержимого, рекомендуется
использовать методы, которые изменяют саму ссылку, например, с помощью
splice для массивов.
<script>
let items = ['Яблоки', 'Бананы'];
function addItem() {
items = [...items, 'Груши']; // Создаём новый массив
}
</script>
<button on:click={addItem}>Добавить элемент</button>
<ul>
{#each items as item}
<li>{item}</li>
{/each}
</ul>
При добавлении элемента в массив через операцию создания нового массива, Svelte будет отслеживать изменения и обновлять интерфейс. Это важно, так как просто изменение внутреннего содержимого массива не приведёт к автоматическому обновлению компонента.
Реактивность является ключевой особенностью Svelte и позволяет разработчикам легко управлять состоянием и обновлять интерфейс при изменении данных. С помощью реактивных переменных, реактивных выражений и store Svelte упрощает создание динамичных, эффективных приложений, минимизируя код, необходимый для обновления DOM.