Организация кода

Muuri — это мощная JavaScript-библиотека для создания динамических сеток с поддержкой перетаскивания, фильтрации и сортировки элементов. Организация кода при работе с Muuri играет критическую роль, особенно при разработке масштабных приложений с большим количеством элементов и сложной логикой управления сеткой.

Правильная структура кода обеспечивает поддерживаемость, масштабируемость и читабельность, что особенно важно при взаимодействии с событиями, кастомными фильтрами и анимациями.


Разделение и модульность

Для крупных проектов рекомендуется разделять код на модули. Это позволяет изолировать:

  • Инициализацию сетки
  • Настройку элементов и их шаблонов
  • Логику фильтрации и сортировки
  • Обработку событий

Пример базовой структуры модулей:

// grid-init.js
import Muuri from 'muuri';

export function initGrid(containerSelector) {
  return new Muuri(containerSelector, {
    dragEnabled: true,
    layout: {
      rounding: false
    },
    dragSort: true
  });
}

// grid-filters.js
export function applyFilter(grid, filterFn) {
  grid.filter(filterFn);
}

// grid-events.js
export function bindEvents(grid) {
  grid.on('dragEnd', (item) => {
    console.log('Item dropped:', item.getElement());
  });
}

Такой подход делает код легко тестируемым и расширяемым, а также упрощает поддержку нескольких сеток на одной странице.


Инициализация и конфигурация сетки

Инициализация сетки Muuri требует выбора контейнера и передачи конфигурации. Основные параметры:

  • dragEnabled — включает перетаскивание элементов.
  • layout — объект с настройками расположения, включая rounding (округление координат).
  • dragSort — разрешает сортировку через перетаскивание.
  • items — массив элементов сетки для начальной загрузки.

Пример расширенной конфигурации:

const grid = new Muuri('.grid', {
  dragEnabled: true,
  dragContainer: document.body,
  layout: {
    fillGaps: true,
    horizontal: false,
    alignRight: false,
    alignBottom: false
  },
  sortData: {
    title: (item) => item.getElement().dataset.title.toLowerCase(),
    date: (item) => new Date(item.getElement().dataset.date)
  }
});

Выделение сортируемых данных через sortData позволяет удобно реализовать динамическую сортировку по различным критериям.


Управление элементами сетки

Работа с элементами требует выборки DOM-узлов и привязки к объектам Muuri. Элементы могут быть:

  • Добавлены динамически через grid.add()
  • Удалены через grid.remove()
  • Изменены через методы show(), hide(), refreshItems()

Пример динамического добавления элемента:

const newItem = document.createElement('div');
newItem.className = 'item';
newItem.dataset.title = 'Новый элемент';
grid.add(newItem);
grid.layout(true);

Метод layout(true) обеспечивает перерасчет расположения после добавления или удаления элементов.


Фильтрация и сортировка

Muuri поддерживает гибкую фильтрацию и сортировку. Фильтры можно реализовать через функции:

grid.filter((item) => item.getElement().dataset.category === 'technology');

Сортировка элементов осуществляется через:

grid.sort((a, b) => a.getElement().dataset.title.localeCompare(b.getElement().dataset.title));

Для больших приложений рекомендуется выносить фильтры и функции сортировки в отдельные модули, чтобы облегчить повторное использование и поддержку.


События и кастомная логика

Muuri предоставляет события на уровне сетки и элементов:

  • dragStart, dragEnd — перетаскивание
  • move — изменение позиции элемента
  • filter — фильтрация
  • sort — сортировка

Пример привязки событий:

grid.on('dragEnd', (item) => {
  console.log('Элемент перемещен:', item.getElement().dataset.title);
});

grid.on('sort', () => {
  console.log('Сетка отсортирована');
});

Для крупных приложений полезно создавать отдельный модуль для событий, который будет импортировать сетку и обрабатывать все пользовательские действия централизованно.


Рекомендации по производительности

  1. Делать батч-обновления при добавлении или удалении нескольких элементов:

    grid.add(newItems, { layout: false });
    grid.layout(true);
  2. Минимизировать вызовы layout(), особенно в циклах.

  3. Использовать refreshItems() после изменений в DOM без полной перестройки сетки.

  4. Для фильтров с большим числом элементов лучше кэшировать значения данных, чтобы уменьшить перебор элементов.


Поддержка динамического контента

Muuri хорошо работает с контентом, который изменяется после загрузки страницы:

  • Анимация при добавлении новых элементов через add() или show().
  • Поддержка ленивой загрузки изображений с вызовом grid.refreshItems() после загрузки.
  • Возможность сортировки и фильтрации новых элементов без полной перестройки сетки.

Пример интеграции с загрузкой изображений:

const images = document.querySelectorAll('.grid img');
images.forEach((img) => {
  img.onl oad = () => {
    grid.refreshItems().layout();
  };
});

Итоговая структура проекта

Для крупных приложений структура может выглядеть так:

/src
  /grid
    grid-init.js       // инициализация сетки
    grid-filters.js    // фильтры и сортировка
    grid-events.js     // обработка событий
    grid-utils.js      // вспомогательные функции для элементов
  /components
    item-template.js   // шаблоны элементов
    modal.js           // всплывающие окна и взаимодействия
  main.js              // основной скрипт, объединяющий модули

Такой подход обеспечивает чистоту кода, упрощает поддержку и расширение функционала, а также позволяет легко интегрировать Muuri в любые современные фронтенд-фреймворки.