vue-masonry-blade
v0.0.6
Published
Composable masonry and virtualization hooks powered by masonry-blade
Maintainers
Readme
vue-masonry-blade
Набор composable-хуков Vue 3 для masonry-blade.
Быстрый старт
Установка
Требуется vue@^3.5.0.
npm install vue-masonry-bladepnpm add vue-masonry-bladeyarn add vue-masonry-bladeЭкспорты
import {
useMasonry,
useMasonryMatrix,
useVirtualMasonry,
getPositionedStyle,
} from 'vue-masonry-blade';Базовый пример
useMasonry() объединяет useMasonryMatrix() и
виртуализацию из useVirtualMasonry().
<script setup lang="ts">
import { onMounted, ref, shallowRef } from 'vue';
import { getPositionedStyle, useMasonry } from 'vue-masonry-blade';
interface Meta {
src: string;
}
const rootRef = ref<HTMLElement | null>(null);
const items = shallowRef([
{ id: 1, width: 800, height: 600, meta: { src: '/images/1.jpg' } },
{ id: 2, width: 800, height: 1100, meta: { src: '/images/2.jpg' } },
{ id: 3, width: 800, height: 700, meta: { src: '/images/3.jpg' } },
]);
const columnCount = ref(4);
const gap = ref(12);
const overscanPx = ref(300);
const breakpoints = shallowRef({ 0: 1, 640: 2, 960: 3, 1280: 4 });
const { containerHeight, recreate, visibleItems, onCreated } = useMasonry<Meta>(
rootRef,
{
columnCount,
gap,
overscanPx,
breakpoints,
},
);
onCreated((matrix) => {
matrix.disableWorker();
});
onMounted(async () => {
await recreate(items.value);
});
</script>
<template>
<section
ref="rootRef"
:style="{ position: 'relative', height: `${containerHeight}px` }"
>
<article
v-for="item in visibleItems"
:key="item.id"
:style="{
...getPositionedStyle(item),
position: 'absolute',
}"
>
<img
:src="item.meta?.src"
:alt="''"
:style="{ width: '100%', height: '100%', objectFit: 'cover' }"
/>
</article>
</section>
</template>Для пагинации или бесконечной подгрузки используйте
append(items)вместо полной пересборки исходного массива.
itemsздесь намеренно хранится вshallowRef(...). Если использоватьref(...)илиreactive(...), Vue обернет вложенные элементы в proxy, а такие значения нельзя передать в worker через structured clone. Это правило относится ко всем элементам, которые вы передаёте вappend()/recreate()или вообще храните в исходной коллекции матрицы.
Nuxt / SSR
useMasonry() и useVirtualMasonry() зависят от DOM-измерений, поэтому в
SSR-среде поддерево, которое использует эти хуки, должно рендериться только на
клиенте.
В Nuxt оборачивайте такую часть в ClientOnly или выносите использование
хуков в client-only компонент.
<ClientOnly>
<MasonryGallery />
</ClientOnly>Composables
useMasonry()
Удобный orchestration-хук, который связывает useMasonryMatrix() и
useVirtualMasonry() в один интерфейс.
const {
matrix,
matrixColumns,
sourceItems,
containerHeight,
resolvedColumnCount,
append,
recreate,
clear,
sort,
onCreated,
visibleMatrix,
visibleItems,
rangeStart,
rangeEnd,
overscanPx,
} = useMasonry(rootRef, {
gap,
columnCount,
breakpoints,
overscanPx,
});useMasonryMatrix()
Создаёт и управляет экземпляром MasonryMatrix.
Подходит, когда нужен прямой контроль над append, recreate, sorting,
breakpoints и состоянием worker'а.
const {
matrix,
matrixColumns,
sourceItems,
containerHeight,
resolvedColumnCount,
append,
recreate,
clear,
sort,
onCreated,
} = useMasonryMatrix(rootRef, gap, columnCount, breakpoints);Хук держит состояние матрицы синхронизированным с шириной контейнера и пересоздаёт ее при изменении ширины,
gap, числа колонок или breakpoints.Через
onCreated((matrix) => {})можно подписаться на первое создание внутреннего экземпляраMasonryMatrix.При изменении breakpoints необходимо заменять весь объект целиком, а не мутировать его на месте.
Для управления worker'ом при необходимости используйте
matrix.valueнапрямую.
useVirtualMasonry()
Строит видимую часть матрицы и возвращает плоский отсортированный список для рендера.
const { visibleMatrix, visibleItems, rangeStart, rangeEnd, overscanPx } =
useVirtualMasonry(rootRef, matrix, matrixColumns, {
overscanPx: 300,
});visibleMatrixсохраняет структуру по колонкам.visibleItems— отсортированный плоский массив видимых элементов
Утилиты
getPositionedStyle()
Преобразует вычисленный элемент матрицы в inline-стили.
const style = getPositionedStyle(item);Возвращаемая форма:
{
width: '...px',
height: '...px',
transform: 'translate(...px, ...px)'
}Форма исходного элемента
Элементы, передаваемые в recreate(items) или append(items), должны иметь
такой вид:
{
id: string | number,
width: number,
height: number,
meta?: unknown
}
widthиheight— это исходные размеры, которые используются для расчёта финального размера элемента внутри сетки.Храните исходную коллекцию в
shallowRef(...)или иным способом следите, чтобы элементы оставались plain-объектами, совместимыми со structured clone. В worker-режиме Vue proxy изref(...)/reactive(...)не проходят structured clone и могут ломатьappend()/recreate().
Contributing
Смотрите CONTRIBUTING.md
Security
Смотрите SECURITY.md
License
Проект распространяется по лицензии MPL 2.0.
Ссылки
- Author: @steelWinds
- Issues: Open an issue
- Telegram: @plutograde
- Email: Send an email
