Работа с REST API

Для работы с библиотекой Isotope необходимо сначала подключить её к проекту. Наиболее распространённый способ — через npm или CDN. После подключения можно инициализировать Isotope на контейнере элементов:

import Isotope from 'isotope-layout';

const grid = document.querySelector('.grid');
const iso = new Isotope(grid, {
  itemSelector: '.grid-item',
  layoutMode: 'masonry',
  percentPosition: true,
  masonry: {
    columnWidth: '.grid-sizer'
  }
});

Ключевые параметры инициализации:

  • itemSelector — CSS-селектор элементов, которые будут управляться библиотекой.
  • layoutMode — режим расположения элементов (masonry, fitRows, vertical).
  • percentPosition — использование процентов для вычисления размеров и положения.
  • masonry.columnWidth — элемент для вычисления ширины колонок при masonry-раскладке.

Загрузка данных из REST API

Для динамического наполнения сетки необходимо получать данные с сервера. Обычно используется fetch или библиотеки вроде Axios. Например, запрос к API для получения списка карточек:

async function fetchItems() {
  try {
    const response = await fetch('https://api.example.com/items');
    if (!response.ok) throw new Error('Ошибка запроса');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(error);
    return [];
  }
}

Особенности работы с REST API:

  • Обработка ошибок (try/catch) и проверка response.ok.
  • Преобразование ответа в JSON.
  • Возврат данных в формате массива объектов для последующего рендеринга.

Рендеринг элементов в DOM

После получения данных с сервера элементы необходимо создать и вставить в контейнер Isotope:

function renderItems(items) {
  const grid = document.querySelector('.grid');
  const fragment = document.createDocumentFragment();

  items.forEach(item => {
    const div = document.createElement('div');
    div.classList.add('grid-item');
    div.innerHTML = `
      ${item.title}
      

${item.title}

${item.description}

`; fragment.appendChild(div); }); grid.appendChild(fragment); iso.appended(fragment.children); iso.layout(); }

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

  • Использование DocumentFragment повышает производительность при вставке большого числа элементов.

  • После добавления новых элементов необходимо вызвать методы Isotope:

    • iso.appended() — уведомление библиотеки о новых элементах.
    • iso.layout() — пересчёт расположения элементов.

Фильтрация и сортировка динамических данных

Isotope позволяет фильтровать и сортировать элементы как статические, так и динамически загруженные:

// Фильтрация по категории
iso.arrange({ filter: '[data-category="books"]' });

// Сортировка по цене
iso.arrange({ sortBy: 'price' });

Для динамических элементов важно, чтобы все новые элементы имели корректные data-атрибуты для фильтров и сортировки:

div.setAttribute('data-category', item.category);
div.setAttribute('data-price', item.price);

Особенности сортировки и фильтрации при работе с API:

  • Фильтры применяются после добавления новых элементов.
  • При изменении данных можно использовать iso.updateSortData() для пересчёта критериев сортировки.

Обработка пагинации и ленивой загрузки

REST API часто возвращает данные порциями. Для интеграции с Isotope это делается через динамическое добавление элементов при скролле или нажатии кнопки:

let page = 1;
const loadMoreBtn = document.querySelector('#load-more');

loadMoreBtn.addEventListener('click', async () => {
  page++;
  const items = await fetchItems(page);
  renderItems(items);
});

Ключевые моменты при работе с пагинацией:

  • Следить за уникальностью элементов (id или другой ключ).
  • После добавления новых элементов вызывать iso.appended() и iso.layout().
  • При использовании ленивой загрузки рекомендуется подключать библиотеку imagesLoaded, чтобы избежать сбоев в расположении из-за задержки загрузки изображений.
import imagesLoaded from 'imagesloaded';

imagesLoaded(grid, () => {
  iso.layout();
});

Динамическое обновление данных

При обновлении существующих элементов важно корректно синхронизировать DOM с данными с сервера:

async function updateItems() {
  const newData = await fetchItems();
  const existingItems = document.querySelectorAll('.grid-item');

  existingItems.forEach(item => item.remove());
  renderItems(newData);
}

Рекомендации:

  • При полном обновлении проще удалить все старые элементы и добавить новые.
  • Для частичного обновления можно использовать iso.remove() для удаления и iso.appended() для добавления новых элементов.
  • Сортировка и фильтры автоматически применяются после вызова iso.layout().