父组件
<template><WaterfallFlow :list="list"/>
</template><script setup lang="ts">import WaterfallFlow from "@/components/WaterfallFlow.vue";
import {reactive} from "vue";
type listType = {height:number,color:string
}
// 随机生成100个高度和颜色的对象
let list = reactive<listType[]>([...Array.from({length:100},()=>({height:Math.floor(Math.random()*250)+50,color:`rgb(${Math.floor(Math.random()*255)},${Math.floor(Math.random()*255)},${Math.floor(Math.random()*255)})`}))])
</script>
子组件
<template><div class="wraps"><div v-for="item in list" class="item" :style="{left: item.left + 'px',top: item.top + 'px',height: item.height + 'px',backgroundColor: item.color,}"></div></div>
</template><script setup lang="ts">
import {defineProps, onMounted} from "vue"const props = defineProps<{list: any[]
}>()const initLayout = () => {// 上下左右间隙距离let margin = 10// 每个元素的宽度let elWidth = 120 + margin// 每行展示的列数let colNumber = Math.floor(document.querySelector(".app-content").clientWidth / elWidth)// 存放元素高度的listlet heightList = []// 遍历所有元素for (let i = 0; i < props.list.length; i++) {let el = props.list[i]// i小于colNumber表示第一行元素if(i < colNumber){el.top = 0el.left = elWidth * iheightList.push(el.height)}else{// 找出最小的高度let minHeight = Math.min(...heightList)// 找出最小高度的索引let minHeightIndex = heightList.indexOf(minHeight)// 设置元素的位置el.left = elWidth * minHeightIndexel.top = minHeight + margin// 更新高度集合heightList[minHeightIndex] = minHeight + el.height + margin}}
}// 监听app-content元素的宽度变化
window.onresize = () => {initLayout()
}onMounted(() => {initLayout()
})
</script><style scoped lang="scss">
.wraps{height: 100%;position: relative;.item{position: absolute;width: 120px;}
}
</style>
效果展示