73 lines
1.3 KiB
Vue
73 lines
1.3 KiB
Vue
<template>
|
|
<div class="waterfall-container" ref="container">
|
|
<div
|
|
v-for="(column, columnIndex) in columns"
|
|
:key="columnIndex"
|
|
class="waterfall-column"
|
|
:style="{ width: `${100 / columnCount}%` }"
|
|
>
|
|
<div
|
|
v-for="item in column"
|
|
:key="item.id"
|
|
class="waterfall-item"
|
|
>
|
|
<slot :item="item">
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, watch } from 'vue'
|
|
|
|
const props = defineProps({
|
|
items: {
|
|
type: Array,
|
|
required: true
|
|
},
|
|
columnCount: {
|
|
type: Number,
|
|
default: 2
|
|
}
|
|
})
|
|
|
|
const columns = ref([])
|
|
|
|
const calculateColumns = () => {
|
|
const cols = Array.from({ length: props.columnCount }, () => [])
|
|
props.items.forEach((item, index) => {
|
|
const columnIndex = index % props.columnCount
|
|
cols[columnIndex].push(item)
|
|
})
|
|
|
|
columns.value = cols
|
|
}
|
|
watch(() => props.items, () => {
|
|
calculateColumns()
|
|
}, { deep: true })
|
|
|
|
onMounted(() => {
|
|
calculateColumns()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.waterfall-container {
|
|
display: flex;
|
|
width: 100%;
|
|
gap: 16px;
|
|
}
|
|
|
|
.waterfall-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
}
|
|
|
|
.waterfall-item {
|
|
break-inside: avoid;
|
|
}
|
|
|
|
/* 默认样式可以移到使用组件时自定义 */
|
|
</style> |