Библиотека Muuri предоставляет мощные возможности для создания сеток с анимацией перетаскивания, сортировки и фильтрации элементов. При использовании с Vue необходимо учитывать реактивность и жизненный цикл компонентов, чтобы корректно инициализировать и управлять сеткой.
Для начала устанавливается Muuri через npm:
npm install muuri
В компоненте Vue библиотека подключается следующим образом:
import Muuri from 'muuri';
Для динамических сеток лучше инициализировать Muuri после рендера
DOM. В Vue 2 это делается в хукe mounted, а в Vue 3 — в
onMounted внутри setup.
Простейший пример инициализации:
mounted() {
this.grid = new Muuri(this.$refs.grid, {
dragEnabled: true,
layoutDuration: 400,
layoutEasing: 'ease'
});
}
Пояснения ключевых параметров:
dragEnabled: true — включает возможность перетаскивания
элементов.layoutDuration — продолжительность анимации перестройки
сетки.layoutEasing — функция смягчения движения при
перестроении сетки.this.$refs.grid ссылается на DOM-элемент контейнера
сетки. Для Vue 3 используется ref из Composition API:
import { ref, onMounted } from 'vue';
import Muuri from 'muuri';
export default {
setup() {
const gridRef = ref(null);
let gridInstance;
onMounted(() => {
gridInstance = new Muuri(gridRef.value, {
dragEnabled: true
});
});
return { gridRef };
}
}
Для сетки с реактивными данными важно корректно обновлять Muuri при
добавлении или удалении элементов. Элементы добавляются с помощью метода
add:
this.grid.add(this.$refs.newItem);
Удаление осуществляется через remove:
const item = this.grid.get(this.$refs.itemToRemove);
this.grid.remove(item, { removeElements: true });
Важно: после изменения DOM рекомендуется вызвать
refreshItems() и layout() для корректного
пересчета позиции элементов:
this.grid.refreshItems().layout();
Muuri напрямую работает с DOM, а Vue управляет виртуальным DOM. Для
синхронизации рекомендуется использовать nextTick, чтобы
гарантировать, что все элементы отрендерены:
import { nextTick } from 'vue';
nextTick(() => {
gridInstance.refreshItems().layout();
});
При работе с массивами Vue 3 можно использовать watch
для автоматического обновления сетки при изменении данных:
import { watch } from 'vue';
watch(items, async () => {
await nextTick();
gridInstance.refreshItems().layout();
});
Muuri поддерживает события, которые можно использовать для реакции на действия пользователя. Например:
this.grid.on('dragEnd', (item) => {
console.log('Элемент перемещен:', item);
});
В Vue 3 с Composition API:
onMounted(() => {
gridInstance.on('dragEnd', (item) => {
console.log('Элемент перемещен:', item);
});
});
Доступны события: add, remove,
layoutStart, layoutEnd,
dragStart, dragEnd и другие. Использование их
позволяет интегрировать Muuri с состоянием приложения Vue.
Muuri позволяет фильтровать элементы по условию:
this.grid.filter((item) => item.getElement().dataset.category === 'active');
Сортировка осуществляется через sort с функцией
сравнения:
this.grid.sort((a, b) => {
return a.getElement().dataset.order - b.getElement().dataset.order;
});
Для динамической сетки Vue можно реализовать реактивную фильтрацию
через watch или вычисляемые свойства.
Для работы с отдельными элементами сетки Muuri предоставляет методы:
getItems() — возвращает массив элементов Muuri.get(itemElement) — возвращает объект элемента Muuri по
DOM-элементу.show(item) / hide(item) — управление
видимостью элементов.Пример скрытия элементов, не соответствующих условию:
this.grid.getItems().forEach(item => {
if (item.getElement().dataset.status !== 'active') {
this.grid.hide(item);
}
});
refreshItems() после завершения всех DOM-операций.layout(false) для мгновенного пересчета
без анимации при начальной загрузке.Если сетка находится на компоненте, который подгружается динамически через маршрутизацию, инициализация Muuri должна выполняться только после рендера:
onMounted(() => {
gridInstance = new Muuri(gridRef.value, { dragEnabled: true });
});
При удалении компонента необходимо уничтожить сетку для освобождения ресурсов:
onBeforeUnmount(() => {
gridInstance.destroy();
});
Muuri поддерживает индивидуальные настройки элементов:
layout — кастомизация поведения перестройки сетки.dragSort — управление тем, как элементы
перетаскиваются.Пример использования кастомного layout:
const grid = new Muuri(gridRef.value, {
layout: {
fillGaps: true,
horizontal: false
}
});
<template>
<div ref="grid" class="grid">
<div v-for="item in items" :key="item.id" class="item" :data-order="item.order">
{{ item.text }}
</div>
</div>
</template>
<script>
import { ref, onMounted, nextTick, watch, onBeforeUnmount } from 'vue';
import Muuri from 'muuri';
export default {
setup() {
const gridRef = ref(null);
let gridInstance;
const items = ref([
{ id: 1, text: 'Элемент 1', order: 1 },
{ id: 2, text: 'Элемент 2', order: 2 },
{ id: 3, text: 'Элемент 3', order: 3 }
]);
onMounted(() => {
gridInstance = new Muuri(gridRef.value, { dragEnabled: true });
});
watch(items, async () => {
await nextTick();
gridInstance.refreshItems().layout();
});
onBeforeUnmount(() => {
gridInstance.destroy();
});
return { gridRef, items };
}
};
</script>
<style>
.grid {
display: flex;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
margin: 5px;
background: #3498db;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
</style>
Этот пример демонстрирует полный цикл: рендер элементов, инициализация сетки, реактивное обновление при изменении данных и очистку при удалении компонента.