实现一个两列的瀑布流布局,支持无限滚动
**思路:**利用flex布局,将列表分为左右两侧,因为这种方式存在一个弊端,就是当有一侧的高度越来越高的时候,滑到底部的时候就会出现一个很明显的高度差,为了修复这个漏洞,写一个算法,计算每一页两侧列表的高度差,举个例子,当左侧高度比右侧高很多的时候,则把下一页列表的第一个数据放在右侧,补齐高度,反之同理;如果数据是无限滚动加载不会滑动到底部的话,则可以不做处理;
代码如下:
<template><div class="prod-list"><van-list v-model:loading="loading" :finished="finish" finished=text="没有更多了" @load="load"><div class="left"><div id="left-box"<productCard v-for="productItem in productListLeft" :key="productItem.id" :itemInfo="productItem" :itemType="itemType"></productCard></div></div><div class="right"><div id="right-box"><productCard v-for="productItem in productListRight" :key="productItem.id" :itemInfo="productItem" :itemType="itemType"></productCard></div></div></van-list></div>
</template>
<script>
import ref from 'vue
import { getAllstores,getAllGoods, getAllsuggest,getAllIntroduction } from '@/api/modules/goods.js'
import productCard from './productcard.vue'export default {props: {itemType: String,activeClass: Number},components: {productCard,Annotate},setup(props) {const page = ref(0)const size = ref(8)const loading = ref(false)const finish = ref(false)const apiMap = { getAllsuggest, getAllGoods, getAllstores, getAllIntroduction }const productList = ref([])const productListLeft = ref([])const productListRight = ref([])const leftHeightNum = ref(0)const rightHeightNum = ref(0)const getContentHeight = () => {const leftBox = document.querySelector('#left-box')const rightBox = document.querySelector('#right-box')leftHeightNum.value = leftBox ? leftBox.offsetHeight : 0rightHeightNum.value = rightBox ? rightBox.offsetHeight : 0}const getorderList = (list, leftList, rightList, flag) = > {for(let i = 0; i < list.length; i++) {if (flag === left') {if (i % 2 ==0 ) {rightList.push(list[i])} else {leftList.push(list[i])} } else {if (i % 2 == 0) {leftList.push(list[i])else {rightList.push(list[i])}}}}const getProduct = (path = 'getAllSuggest', className = 0, index) =>loading.value = trueconst targetApi = apiMap[path]const params = {page: page .value.size: size.value,body: path !="getAllSuggest' || path != 'getAllIntroduction'? {goodsTypeID: className.} : null}targetApi(params).then(async res => {if (res.code === 20000) {if (page.value == 0) {productList.value = []productListLeft.value = []productListRight.value = []}let leftList = []let rightList = []productList.value = res.data.listfinish.value = page.value >= Number(res.data.totalPages)if (productList.value.length > 0) {await getContentHeight()if (page.value === 1) {getorderList(productList.value, leftList, rightList, 'right')} else {if (leftHeightNum.value > rightHeightNum.value && leftHeightNum.value - rightHeightNum.value > 100) {let firstItem = productList.value.shift()rightList.push(firstItem)getorderList(productList.value, leftList, rightList,'left') } } else if ( leftHeightNum.value < rightHeightNum.value && rightHeightNum.value - leftHeightNum.value > 100) {let firstItem = productList.value.shift()leftList.push(firstItem)getorderList(productList.value, leftList, rightList,'right')} else {getorderList(productList.value, leftList,rightList,'right')}}productListLeft.value = [...productListLeft.value,...leftList]productListRight.value = [...productListRight.value, ...rightList]loading.value = false} else {loading.value=false;finish.value =true}}).catch(err => {loading.value=falsefinish.value =true})}const onLoad = () => {page.value += 1getProduct(props.itemType,props.activeClass)}// 重置数据const resetData = () => {page.value = 1productList.value = []productListLeft.value = []productListRight.value = []loading.value = falsefinish.value = false}return {productList,loadingfinish,onLoad,page,getProduct,productListLeft,productListRight,resetData,}
</script>
<style lang="scss"scoped>
.prod-list {.container {width: 100%;display: flex;.left {flex: 1;margin-right: 8px;}.right {flex: 1;}}.van-list {:deep(.van-list finished-text) {width: 100%;}:deep(.van-list placeholder) {width: 100%;}}
}
</style>