Vue JS集成Masonry瀑布流首次加载布局错乱仅resize后正常如何解决
问题原因
- 你在
mounted钩子中直接初始化Masonry时,页面内的图片资源尚未完成加载,此时Masonry计算布局使用的是图片未加载的默认高度,导致布局计算错误。 - 手动调整浏览器窗口时会触发Masonry的自动重排逻辑,此时图片已加载完成,高度计算正确,所以布局恢复正常。
- 补充:原代码中
v-for遍历的变量名和根数据名均为data存在命名冲突,也可能引发渲染异常。
可行解决方案
方案1:使用imagesLoaded插件(官方推荐)
这是Masonry官方推荐的配套方案,专门用于监听图片加载完成后触发重排:
- 先安装依赖:
npm install imagesloaded masonry-layout
- 修改组件代码:
<template> <div class="grid"> <div class="grid-item" v-for="(item, index) in data" :key="index"> <router-link :to="{ name: 'painting', params: { id: index } }"> <img :src="publicURL + item.images.thumbnail.substring(1)" /> </router-link> </div> </div> </template> <script> import data from "../assets/data.json"; import Masonry from 'masonry-layout'; import imagesLoaded from 'imagesloaded'; export default { name: "Galleria", data() { return { data: data, publicURL: "https://6e222.csb.app", msnry: null }; }, mounted() { const grid = document.querySelector(".grid"); // 初始化Masonry this.msnry = new Masonry(grid, { columnWidth: 25, itemSelector: '.grid-item' }); // 所有图片加载完成后触发重排 imagesLoaded(grid, () => { this.msnry.layout(); }); } }; </script>
方案2:预设图片宽高比(无额外依赖)
如果不想引入第三方依赖,可以提前给图片容器设置固定宽高比,提前占住高度,让Masonry初始化时就能拿到正确的元素高度:
/* 新增样式 */ .grid-item { aspect-ratio: 2/3; /* 按你的图片实际比例调整 */ } .grid-item img { width: 100%; height: 100%; object-fit: cover; }
方案3:逐张图片加载后触发重排
如果图片数量较少,也可以监听单张图片加载事件,每加载完一张就触发一次重排:
<template> <div class="grid"> <div class="grid-item" v-for="(item, index) in data" :key="index"> <router-link :to="{ name: 'painting', params: { id: index } }"> <img :src="publicURL + item.images.thumbnail.substring(1)" @load="onImgLoad" /> </router-link> </div> </div> </template> <script> import data from "../assets/data.json"; import Masonry from 'masonry-layout'; export default { name: "Galleria", data() { return { data: data, publicURL: "https://6e222.csb.app", msnry: null }; }, mounted() { const grid = document.querySelector(".grid"); this.msnry = new Masonry(grid, { columnWidth: 25, itemSelector: '.grid-item' }); }, methods: { onImgLoad() { this.msnry?.layout(); } } }; </script>
内容的提问来源于stack exchange,提问作者Alejandro Arias Aguilar
相关产品推荐
相关产品推荐

