Реактивность и обновление состояния

В Svelte реактивность встроена на уровне языка и позволяет автоматически отслеживать изменения состояния и обновлять интерфейс без необходимости вручную управлять DOM. Библиотека Carbon Components Svelte строится поверх этой концепции, предоставляя готовые компоненты, которые реагируют на изменения данных напрямую.

Реактивные переменные

Любая переменная, объявленная в компоненте, автоматически становится частью реактивного контекста. При изменении её значения Svelte обновляет все места, где она используется. Для реактивных вычислений применяется специальная конструкция $::

<script>
  import { Button } from 'carbon-components-svelte';

  let count = 0;

  $: doubled = count * 2;
</script>

<Button on:click={() => count += 1}>Увеличить</Button>
<p>Счётчик: {count}</p>
<p>Удвоенное значение: {doubled}</p>

Ключевые моменты:

  • $: создаёт реактивное выражение, которое пересчитывается при изменении зависимых переменных.
  • Любая переменная, используемая в выражении, автоматически становится его зависимостью.
  • Carbon Components Svelte корректно обновляет визуальное состояние компонентов при изменении их props.

Связь состояния и props компонентов

Компоненты Carbon Svelte получают данные через свойства (props). При изменении значения props компонент автоматически перерисовывается, поддерживая синхронизацию состояния:

<script>
  import { TextInput } from 'carbon-components-svelte';
  let inputValue = '';
</script>

<TextInput bind:value={inputValue} labelText="Введите текст" />
<p>Вы ввели: {inputValue}</p>

Особенности использования bind:value:

  • Двусторонняя привязка автоматически синхронизирует внутреннее состояние компонента и переменную.
  • Это особенно полезно для форм, фильтров и других интерактивных элементов Carbon.

Реактивные списки и циклы

Компоненты часто используются для отображения коллекций данных. В Svelte это делается через цикл {#each}. При изменении массива интерфейс обновляется автоматически:

<script>
  import { ListItem, List } from 'carbon-components-svelte';
  let items = ['Элемент 1', 'Элемент 2', 'Элемент 3'];

  function addItem() {
    items = [...items, `Элемент ${items.length + 1}`];
  }
</script>

<List>
  {#each items as item}
    <ListItem>{item}</ListItem>
  {/each}
</List>
<button on:click={addItem}>Добавить элемент</button>

Важные моменты:

  • Использование spread-оператора при обновлении массива гарантирует, что Svelte заметит изменение.
  • Carbon Components Svelte корректно применяет стили и поведение к динамически добавленным элементам.

Реактивные события и методы

Компоненты Carbon имеют собственные события, такие как on:click, on:change, on:input. Эти события можно связывать с реактивными переменными для мгновенного обновления состояния:

<script>
  import { Checkbox } from 'carbon-components-svelte';
  let accepted = false;
</script>

<Checkbox bind:checked={accepted} labelText="Согласен с условиями" />
<p>{accepted ? 'Условия приняты' : 'Условия не приняты'}</p>

Особенности работы с событиями:

  • bind:checked обеспечивает двустороннюю реактивность для состояния checked.
  • Изменение переменной автоматически обновляет отображение других компонентов или текста.

Реактивные вычисления с компонентами Carbon

Иногда нужно, чтобы изменение одного компонента влияло на несколько других элементов интерфейса. Реактивные выражения $: позволяют централизовать такую логику:

<script>
  import { Slider, NumberInput } from 'carbon-components-svelte';

  let value = 50;

  $: adjustedValue = value * 1.2;
</script>

<Slider bind:value min={0} max={100} step={1} />
<NumberInput bind:value={value} min={0} max={100} />
<p>Скорректированное значение: {adjustedValue}</p>

Выводы по реактивности:

  • Все компоненты Carbon Svelte мгновенно реагируют на изменения переменных.
  • Комбинирование $: и bind: позволяет строить сложные интерфейсы без явного управления DOM.
  • С помощью реактивных вычислений можно создавать производные состояния и синхронизировать данные между несколькими компонентами.

Практика оптимизации реактивности

Для больших приложений важно избегать лишних перерендеров. В Carbon Svelte это достигается:

  • Изоляцией состояния в локальные переменные компонента.
  • Использованием реактивных выражений только там, где это необходимо.
  • Обновлением массивов и объектов через копирование (spread-оператор), чтобы Svelte мог отследить изменения.
<script>
  import { DataTable, Table, TableRow, TableCell } from 'carbon-components-svelte';

  let rows = [{ name: 'Алексей', age: 30 }, { name: 'Мария', age: 25 }];

  function updateAge(index, newAge) {
    rows = rows.map((row, i) => i === index ? { ...row, age: newAge } : row);
  }
</script>

<DataTable {rows}>
  {#each rows as row, i}
    <TableRow>
      <TableCell>{row.name}</TableCell>
      <TableCell>{row.age}</TableCell>
    </TableRow>
  {/each}
</DataTable>

Использование spread-оператора и реактивных переменных гарантирует, что Carbon Components обновит визуальные элементы корректно, без багов и конфликтов состояния.