H5移动端vue-masonry + van-list实现瀑布流懒加载效果
1. 安装两个库
npm install vue-masonry --save
npm i vant@latest-v2 --save
2. 全局注册
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Vant from 'vant'
import 'vant/lib/index.css'
import {VueMasonryPlugin} from 'vue-masonry';
import '@/assets/global.css'
Vue.config.productionTip = false
Vue.use(Vant)
Vue.use(VueMasonryPlugin)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
3. 使用
vue-masonry
的一些属性
item-selector=".item"
列表元素 DOM 项目选择器;transition-duration="0.3s"
过渡的持续时间;column-width="#test"
列宽的元素选择器。可以是选择器字符串或数字;origin-left=“false”
设置为默认将元素分组到右侧而不是左侧;origin-top="false"
默认情况下将元素分组到底部而不是顶部;stamp=".stamp"
指定在布局中标记哪些元素;gutter=".gutter-block-selector"
指定[项目元素之间的水平空间]。可以是选择器字符串或数字。将 gutter 设置为 Element 或 Selector String 以使用元素的外部宽度;fit-width="true"
设置容器的宽度以适合可用的列数;horizontal-order="true"
布置项目以(主要)保持水平从左到右的顺序;stagger="0.03s"
错开项目过渡,因此项目一个接一个地逐步过渡。设置为 CSS,时间格式,“0.03s”,或以毫秒为单位的数字,30。destroy-delay="0"
masonry.destroy()
当容器被销毁时,在卸载砖石之前等待的时间(以毫秒为单位) 。这在页面/路由转换期间很有用,以确保在转换发生时布局是一致的。
<template>
<div :style="{ padding: `10px` }">
<van-list v-model="loading" :finished="finished" finished-text="我是有底线的" @load="onLoad" :immediate-check="false"
:style="{ width: `${screenWidth - 20}px` }">
<van-cell :style="{ padding: `10px` }">
<div v-masonry transition-duration="0s" item-selector=".item" gutter="10">
<div v-masonry-tile class="item" v-for="(item, index) in styleList " :key="item.id"
:style="{ width: `${imgWidth}px`, marginBottom: '4px' }" @click="goto(item)">
<img :src="item.src" alt="">
<div :style="{ position: 'absolute', bottom: '10px', right: '10px', background: '#fff' }">{{ index }}</div>
</div>
</div>
</van-cell>
</van-list>
</div>
</template>
<script>
export default {
data() {
return {
screenWidth: null,
screenHeight: null,
imgWidth: null,
styleList: [
{ id: null, type: '商务1', src: "https://www.freeimg.cn/i/2024/01/08/659b50c926020.png" },
{ id: null, type: '商务2', src: "https://www.freeimg.cn/i/2024/01/08/659b50ca0646d.jpg" },
{ id: null, type: '商务3', src: "https://www.freeimg.cn/i/2024/01/08/659b50c9e9d0f.png" },
{ id: null, type: '商务4', src: "https://www.freeimg.cn/i/2024/01/08/659b50c926020.png" },
{ id: null, type: '商务5', src: "https://www.freeimg.cn/i/2024/01/08/659b50ca0646d.jpg" },
{ id: null, type: '商务6', src: "https://www.freeimg.cn/i/2024/01/08/659b50c9e9d0f.png" },
{ id: null, type: '商务7', src: "https://www.freeimg.cn/i/2024/01/08/659b50c926020.png" },
{ id: null, type: '商务8', src: "https://www.freeimg.cn/i/2024/01/08/659b50ca0646d.jpg" },
{ id: null, type: '商务9', src: "https://www.freeimg.cn/i/2024/01/08/659b50c9e9d0f.png" },
{ id: null, type: '商务10', src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F8080ba2d-d5e8-4f98-96d0-95c69d5862b8%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1706774872&t=b1900e9188c67df586f8e3abacb0290a" },
], // 图片列表
// 状态
loading: false,
finished: false,
curPage: 1,
total: 0
};
},
created() {
this.screenWidth = document.body.clientWidth; // 屏幕宽
this.screeHeight = document.body.clientHeight; // 屏幕高
console.log('screenWidth:' + this.screenWidth);
console.log('screeHeight:' + this.screeHeight);
this.imgWidth = (this.screenWidth - 50) / 2
this.getList();
},
methods: {
getList() {
this.styleList.map(r => { r.id = Math.floor(Math.random() * 999999999) + 1 })
},
onLoad() {
console.log('到底了,需要继续加载');
// 特判,当总数据小于10条时
if (this.total <= 10 && this.total !== 0) {
this.finished = true;
return;
}
// 判断当前页数是否等于总页数,并且初始长度不等于0,防止从详情页返回出现bug,造成误判
if (this.curPage === Math.ceil(this.total / 10) && this.total !== 0) {
this.finished = true;
return;
}
this.curPage++;
// http({
// url: `/gateway?cityId=310100&pageNum=${this.curPage}&pageSize=10&type=1&k=908466`,
// headers: {
// 'X-Host': 'mall.film-ticket.film.list'
// }
// }).then((res) => {
// this.filmList = this.addNewFilmItems(res.data.data.films);
// this.total = res.data.data.total
// console.log(this.filmList);
// })
this.getList();
let list = [
{ id: null, type: '商务1', src: "https://www.freeimg.cn/i/2024/01/08/659b50c926020.png" },
{ id: null, type: '商务2', src: "https://www.freeimg.cn/i/2024/01/08/659b50ca0646d.jpg" },
{ id: null, type: '商务3', src: "https://www.freeimg.cn/i/2024/01/08/659b50c9e9d0f.png" },
{ id: null, type: '商务4', src: "https://www.freeimg.cn/i/2024/01/08/659b50c926020.png" },
{ id: null, type: '商务5', src: "https://www.freeimg.cn/i/2024/01/08/659b50ca0646d.jpg" },
{ id: null, type: '商务6', src: "https://www.freeimg.cn/i/2024/01/08/659b50c9e9d0f.png" },
{ id: null, type: '商务7', src: "https://www.freeimg.cn/i/2024/01/08/659b50c926020.png" },
{ id: null, type: '商务8', src: "https://www.freeimg.cn/i/2024/01/08/659b50ca0646d.jpg" },
{ id: null, type: '商务9', src: "https://www.freeimg.cn/i/2024/01/08/659b50c9e9d0f.png" },
{ id: null, type: '商务10', src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F8080ba2d-d5e8-4f98-96d0-95c69d5862b8%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1706774872&t=b1900e9188c67df586f8e3abacb0290a" },
]
list.map(r => { r.id = Math.floor(Math.random() * 999999999) + 1 })
this.styleList.push(...list);
this.loading = false;
},
addNewFilmItems(newFilmList) {
return this.filmList.concat(newFilmList);
},
filteredActors(actors) {
const actorsName = actors.map((item) => {
return item = item.name;
});
return actorsName.join(' ');
},
},
};
</script>
注:使用中遇到class被覆盖的情况,原因暂时没有排查,先使用行内样式解决此问题。