Muuri — это мощная библиотека для организации динамических
сеток с возможностью сортировки, фильтрации и перетаскивания
элементов. Одним из ключевых инструментов управления содержимым сетки
является фильтрация по атрибутам данных
(data-*). Она позволяет гибко управлять отображением
элементов без необходимости изменения структуры DOM или применения
сложных условий через JavaScript.
Каждый элемент сетки в Muuri — это HTML-элемент, который может
содержать кастомные атрибуты. Для фильтрации удобно
использовать data-* атрибуты:
<div class="grid">
<div class="item" data-category="fruit" data-price="low">
<div class="item-content">Яблоко</div>
</div>
<div class="item" data-category="fruit" data-price="high">
<div class="item-content">Манго</div>
</div>
<div class="item" data-category="vegetable" data-price="low">
<div class="item-content">Морковь</div>
</div>
<div class="item" data-category="vegetable" data-price="high">
<div class="item-content">Авокадо</div>
</div>
</div>
В этом примере каждый элемент имеет атрибуты
data-category и data-price, которые будут
использоваться для фильтрации.
Для работы с фильтрацией необходимо создать экземпляр сетки Muuri:
const grid = new Muuri('.grid', {
layout: {
rounding: false
}
});
Ключевой момент — это возможность фильтровать элементы через метод
filter(), передавая ему функцию, возвращающую
true/false для каждого элемента.
Для фильтрации элементов по значению атрибута можно использовать следующий подход:
function filterByCategory(category) {
grid.filter(item => item.getElement().dataset.category === category);
}
// Пример использования:
filterByCategory('fruit'); // Покажет только элементы с data-category="fruit"
Пояснение:
item.getElement() возвращает DOM-элемент сетки.dataset позволяет получить объект всех
data-* атрибутов элемента.true сохраняет элемент в сетке,
false скрывает.Muuri позволяет комбинировать условия для более сложной фильтрации:
function filterByCategoryAndPrice(category, price) {
grid.filter(item => {
const el = item.getElement();
return el.dataset.category === category && el.dataset.price === price;
});
}
// Пример использования:
filterByCategoryAndPrice('vegetable', 'low'); // Покажет только морковь
Это дает полную гибкость, позволяя комбинировать
категории, ценовые диапазоны или любые
другие данные, закодированные в data-*.
Чтобы показать все элементы после применения фильтров, можно использовать:
grid.filter(() => true);
Или, альтернативно, удалить фильтрующую функцию:
grid.show(grid.getItems());
Часто требуется фильтровать элементы через кнопки или селекты:
<button data-filter="fruit">Фрукты</button>
<button data-filter="vegetable">Овощи</button>
<button data-filter="all">Все</button>
const buttons = document.querySelectorAll('button[data-filter]');
buttons.forEach(btn => {
btn.addEventListener('click', () => {
const filter = btn.dataset.filter;
if (filter === 'all') {
grid.filter(() => true);
} else {
grid.filter(item => item.getElement().dataset.category === filter);
}
});
});
Такое решение позволяет динамически менять фильтры без перезагрузки страницы.
Для более гибкой фильтрации, например, по части строки атрибута, можно использовать регулярные выражения:
grid.filter(item => /fruit|vegetable/.test(item.getElement().dataset.category));
Это позволяет показывать сразу несколько категорий или фильтровать по частичному совпадению.
Для комбинирования нескольких фильтров удобно хранить их состояния в объекте:
const filters = {
category: 'fruit',
price: 'low'
};
grid.filter(item => {
const el = item.getElement();
const matchCategory = filters.category ? el.dataset.category === filters.category : true;
const matchPrice = filters.price ? el.dataset.price === filters.price : true;
return matchCategory && matchPrice;
});
Такой подход позволяет легко обновлять фильтры по отдельным критериям без переписывания всей функции.
Если в сетку добавляются новые элементы после инициализации,
фильтрация по data-* продолжает работать корректно:
const newItem = document.createElement('div');
newItem.classList.add('item');
newItem.dataset.category = 'fruit';
newItem.dataset.price = 'medium';
newItem.innerHTML = '<div class="item-content">Банан</div>';
grid.add(newItem);
// Применяем текущий фильтр снова
grid.filter(item => item.getElement().dataset.category === 'fruit');
Muuri автоматически интегрирует новые элементы в текущую сетку и фильтры.
dataset для каждого элемента при
инициализации.sort().data-* фильтрациейdata-* атрибуты позволяют хранить метаданные
непосредственно в элементах DOM.grid.filter() принимает функцию, возвращающую
true/false для каждого элемента.Такой подход делает Muuri гибким и расширяемым инструментом для построения интерактивных и динамических сеток с контролируемым отображением элементов.