Условный рендеринг и циклы

В Svelte условный рендеринг позволяет отображать или скрывать части пользовательского интерфейса на основе логики, заложенной в компоненте. Вместо использования конструкции, аналогичной v-if в Vue или if в JSX для React, Svelte имеет собственный синтаксис для этого, что делает код более чистым и понятным.

Использование блока {#if}

Для реализации условного рендеринга в Svelte используется специальный блок {#if}. С его помощью можно отобразить элемент только в том случае, если условие истинно. Например, следующая конструкция позволяет показывать блок только в том случае, если переменная isVisible равна true:

<script>
  let isVisible = true;
</script>

{#if isVisible}
  <p>Этот элемент отображается, если isVisible равно true.</p>
{/if}

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

Блок {#else} и {#elseif}

Вместо обычной конструкции if-else, Svelte использует {#else} для задания альтернативной ветки выполнения. С помощью блока {#elseif} можно добавить дополнительные условия для проверки, делая код компактным и читаемым.

<script>
  let isVisible = false;
</script>

{#if isVisible}
  <p>Этот элемент отображается, если isVisible равно true.</p>
{:else}
  <p>Этот элемент отображается, если isVisible равно false.</p>
{/if}

Использование {#elseif} аналогично конструкции else if в других языках программирования и позволяет комбинировать несколько условий в одном блоке:

<script>
  let status = "loading";
</script>

{#if status === "loading"}
  <p>Загрузка...</p>
{:elseif status === "success"}
  <p>Данные загружены успешно!</p>
{:else}
  <p>Произошла ошибка при загрузке данных.</p>
{/if}

Циклы в Svelte

В Svelte для рендеринга списков или повторяющихся элементов используется конструкция {#each}. Эта конструкция позволяет перебирать массивы и отображать каждый элемент на основе заданного шаблона.

Простейший цикл с {#each}

Цикл {#each} в Svelte использует синтаксис, схожий с другими фреймворками, например, v-for в Vue или map в React. Для перебора элементов массива и отображения их в шаблоне достаточно записать:

<script>
  let items = ["Яблоки", "Бананы", "Груши"];
</script>

<ul>
  {#each items as item}
    <li>{item}</li>
  {/each}
</ul>

В этом примере массив items перебирается и для каждого элемента создается новый элемент списка <li>. Важно заметить, что в Svelte цикл выполняется только при изменении массива.

Индексы в цикле

Svelte позволяет использовать индекс текущего элемента в массиве, что полезно для реализации сложных структур или при необходимости отслеживания позиции элемента.

<script>
  let fruits = ["Яблоки", "Бананы", "Груши"];
</script>

<ul>
  {#each fruits as fruit, index}
    <li>{index + 1}. {fruit}</li>
  {/each}
</ul>

Здесь переменная index будет содержать текущий индекс элемента в массиве, который можно использовать в шаблоне.

Рендеринг элементов с ключами

Для оптимизации рендеринга в Svelte можно использовать ключи в цикле с помощью атрибута key. Это позволяет фреймворку эффективно обновлять только те элементы, которые изменились, вместо того чтобы перерисовывать все элементы списка.

<script>
  let fruits = ["Яблоки", "Бананы", "Груши"];
</script>

<ul>
  {#each fruits as fruit (fruit)}
    <li>{fruit}</li>
  {/each}
</ul>

В данном примере используется значение элемента fruit в качестве ключа. Это позволяет Svelte отслеживать каждый элемент и предотвращать его перерисовку, если его данные не изменились.

Удаление элементов из массива

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

<script>
  let fruits = ["Яблоки", "Бананы", "Груши"];

  function removeFruit(fruit) {
    fruits = fruits.filter(f => f !== fruit);
  }
</script>

<ul>
  {#each fruits as fruit (fruit)}
    <li>
      {fruit} <button on:click={() => removeFruit(fruit)}>Удалить</button>
    </li>
  {/each}
</ul>

В этом примере при нажатии на кнопку элемент удаляется из списка, и Svelte обновляет DOM, показывая актуальное состояние.

Циклы и условные операторы

Часто возникает необходимость комбинировать условный рендеринг и циклы. Например, когда необходимо показать блок, если список пуст, или изменить внешний вид элементов в зависимости от их состояния:

<script>
  let fruits = [];
</script>

{#if fruits.length === 0}
  <p>Список фруктов пуст.</p>
{:else}
  <ul>
    {#each fruits as fruit}
      <li>{fruit}</li>
    {/each}
  </ul>
{/if}

В данном примере условие проверяет, есть ли элементы в массиве, и, в зависимости от этого, отображается сообщение или список.

Рендеринг с асинхронными данными

Работа с асинхронными данными в Svelte также поддерживает условный рендеринг и циклы. При получении данных из API или при работе с обещаниями можно использовать await для ожидания ответа и рендеринга в зависимости от состояния.

<script>
  let loading = true;
  let data = [];

  fetch('https://api.example.com/fruits')
    .then(response => response.json())
    .then(json => {
      data = json;
      loading = false;
    });
</script>

{#if loading}
  <p>Загрузка...</p>
{:else}
  <ul>
    {#each data as fruit}
      <li>{fruit}</li>
    {/each}
  </ul>
{/if}

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

Заключение

В Svelte условный рендеринг и циклы предоставляют мощные и гибкие механизмы для динамического отображения данных. Блоки {#if}, {#else}, {#each} и их сочетания позволяют создавать эффективные и читаемые компоненты. Реактивность и оптимизация рендеринга делают работу с большими и динамичными интерфейсами удобной и быстрой.