vue实现图片瀑布流
Vue 实现图片瀑布流的方法
使用 CSS 多列布局
CSS 的 column-count 和 column-gap 属性可以快速实现简单的瀑布流效果。这种方法适合图片高度差异不大的场景。
<template>
<div class="waterfall-container">
<div v-for="(img, index) in images" :key="index" class="waterfall-item">
<img :src="img.src" :alt="img.alt">
</div>
</div>
</template>
<style>
.waterfall-container {
column-count: 3;
column-gap: 15px;
}
.waterfall-item {
break-inside: avoid;
margin-bottom: 15px;
}
</style>
使用 JavaScript 计算布局
通过 JavaScript 动态计算每张图片的位置,可以实现更灵活的瀑布流效果,适合图片高度差异较大的场景。
<template>
<div class="waterfall-container" ref="container">
<div
v-for="(img, index) in images"
:key="index"
class="waterfall-item"
:style="{ top: `${img.top}px`, left: `${img.left}px`, width: `${columnWidth}px` }"
>
<img :src="img.src" :alt="img.alt" @load="handleImageLoad">
</div>
</div>
</template>
<script>
export default {
data() {
return {
images: [],
columnWidth: 200,
columnHeights: [],
};
},
mounted() {
this.initWaterfall();
window.addEventListener('resize', this.initWaterfall);
},
methods: {
initWaterfall() {
const containerWidth = this.$refs.container.offsetWidth;
const columnCount = Math.floor(containerWidth / this.columnWidth);
this.columnHeights = new Array(columnCount).fill(0);
},
handleImageLoad(event) {
const img = event.target;
const minHeight = Math.min(...this.columnHeights);
const columnIndex = this.columnHeights.indexOf(minHeight);
this.images.push({
src: img.src,
alt: img.alt,
top: minHeight,
left: columnIndex * this.columnWidth,
});
this.columnHeights[columnIndex] += img.height + 15;
},
},
};
</script>
使用第三方库
如果需要更复杂的功能(如懒加载、无限滚动等),可以使用第三方库如 vue-waterfall 或 masonry-layout。
安装 vue-waterfall:
npm install vue-waterfall
示例代码:
<template>
<vue-waterfall :list="images" :gutter="15" :width="240">
<template v-slot:item="{ item }">
<img :src="item.src" :alt="item.alt">
</template>
</vue-waterfall>
</template>
<script>
import VueWaterfall from 'vue-waterfall';
export default {
components: { VueWaterfall },
data() {
return {
images: [],
};
},
};
</script>
响应式设计
为了适应不同屏幕尺寸,可以通过监听窗口大小动态调整列数和图片宽度。
methods: {
handleResize() {
const containerWidth = this.$refs.container.offsetWidth;
this.columnWidth = Math.floor(containerWidth / 3);
this.initWaterfall();
},
},
mounted() {
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
},
性能优化
对于大量图片的场景,可以使用懒加载技术(如 vue-lazyload)减少初始加载时间。
<template>
<div class="waterfall-container">
<div v-for="(img, index) in images" :key="index" class="waterfall-item">
<img v-lazy="img.src" :alt="img.alt">
</div>
</div>
</template>
<script>
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload, {
preLoad: 1.3,
attempt: 3,
});
</script>





