Функции сравнения

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


Основы использования функций сравнения

Функции сравнения в Muuri передаются в метод sort экземпляра сетки. Сигнатура функции соответствует стандарту JavaScript Array.prototype.sort: она принимает два аргумента — объекты itemA и itemB (экземпляры Muuri.Item) и возвращает число:

  • отрицательное числоitemA располагается перед itemB
  • ноль — порядок элементов не изменяется
  • положительное числоitemA располагается после itemB

Пример базовой функции сравнения по числовому значению атрибута:

grid.sort((itemA, itemB) => {
    const valueA = itemA.getElement().dataset.value;
    const valueB = itemB.getElement().dataset.value;
    return Number(valueA) - Number(valueB);
});

Здесь используется dataset.value, хранящий числовое значение, и элементы сортируются по возрастанию.


Сравнение по строковым значениям

Для сортировки по текстовым значениям следует использовать метод localeCompare для корректной обработки символов и локализации:

grid.sort((itemA, itemB) => {
    const nameA = itemA.getElement().querySelector('.title').textContent;
    const nameB = itemB.getElement().querySelector('.title').textContent;
    return nameA.localeCompare(nameB, 'ru', { sensitivity: 'base' });
});

Особенности:

  • 'ru' указывает на русский язык для правильного сравнения кириллицы.
  • sensitivity: 'base' игнорирует регистр и диакритические знаки.

Многоуровневая сортировка

Функции сравнения могут объединять несколько критериев. Например, сначала по дате, затем по имени:

grid.sort((itemA, itemB) => {
    const dateA = new Date(itemA.getElement().dataset.date);
    const dateB = new Date(itemB.getElement().dataset.date);

    if (dateA - dateB !== 0) {
        return dateA - dateB;
    }

    const nameA = itemA.getElement().dataset.name;
    const nameB = itemB.getElement().dataset.name;
    return nameA.localeCompare(nameB);
});

В этом примере первичный критерий — дата, вторичный — имя. Если даты совпадают, порядок определяется по алфавиту.


Сортировка с учетом пользовательских данных

Muuri позволяет хранить любые пользовательские данные в объекте item._data. Это удобно для сложных проектов, когда элементы имеют свойства, не отображаемые в DOM:

grid.sort((itemA, itemB) => {
    return itemA._data.priority - itemB._data.priority;
});

Здесь сортировка выполняется по пользовательскому полю priority, и нет необходимости обращаться к DOM.


Обратный порядок сортировки

Для реализации обратного порядка достаточно изменить знак возвращаемого значения:

grid.sort((itemA, itemB) => {
    const valueA = Number(itemA.getElement().dataset.value);
    const valueB = Number(itemB.getElement().dataset.value);
    return valueB - valueA; // меняем местами A и B
});

Такой прием работает для любых числовых и строковых критериев, комбинируемых с localeCompare или другими функциями.


Динамическая сортировка

Функции сравнения могут быть динамическими, реагируя на состояние приложения:

const sortBy = 'price'; // может меняться
grid.sort((itemA, itemB) => {
    const a = Number(itemA.getElement().dataset[sortBy]);
    const b = Number(itemB.getElement().dataset[sortBy]);
    return a - b;
});

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


Сортировка с кастомными правилами

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

const priorityOrder = { high: 1, medium: 2, low: 3 };

grid.sort((itemA, itemB) => {
    const a = priorityOrder[itemA.getElement().dataset.priority];
    const b = priorityOrder[itemB.getElement().dataset.priority];
    return a - b;
});

Это позволяет задавать произвольный приоритет элементов, не зависящий от их естественного порядка.


Производительность функций сравнения

  • Минимизировать обращения к DOM: данные лучше хранить в dataset или в _data, чтобы избежать частых вызовов querySelector и textContent.
  • Кэшировать вычисления: если вычисление критерия сложное (например, парсинг даты), лучше кэшировать его при инициализации элементов.
  • Локальные сравнения: при сортировке большого числа элементов использовать простые числовые или индексные значения, а не строки.

Интеграция с фильтрацией и анимацией

Muuri автоматически обновляет положение элементов после сортировки. При использовании анимации порядок изменяется плавно:

grid.sort((itemA, itemB) => itemA._data.rank - itemB._data.rank, { layout: 'instant' });

Опция layout: 'instant' позволяет отключить анимацию, что ускоряет перестановку при больших сетках.


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