瀑布流即參差不齊的多欄布局,可向下滾動,且隨著向下滑動不斷加載新的內容

image.png
以下是一些實現(xiàn)方式,只提供用于兩欄布局瀑布流的簡單思路,多欄瀑布流按照思路也可很快實現(xiàn),自己去想,懶得寫了
js實現(xiàn)
利用js計算和填充數(shù)據(jù)
直接上代碼
<view class="content">
<view class="content-left">
<view class="item" v-for="item in listLeft" :key="item.index">{{ item.content}}</view>
</view>
<view class="content-right">
<view class="item" v-for="item in listRight" :key="item.index">{{ item.content }}</view>
</view>
<view class="noShow">
<view ref="list" class="item" v-for="item in list" :key="item.index">{{ item.content }}</view>
</view>
</view>
.content {
padding: 10rpx;
display: flex;
justify-content: space-between;
}
.content-left {
display: flex;
width: calc(50% - 10rpx);
flex-direction: column;
}
.content-right {
display: flex;
width: calc(50% - 10rpx);
flex-direction: column;
}
.item {
padding: 10rpx;
margin-bottom: 10rpx;
border: 1rpx solid #ccc;
}
.noShow {
width: calc(50% - 10rpx);
position: absolute;
left: 10000px;
bottom: 10000px;
}
this.$nextTick(() => {
let elLeftHeight = 0;
let elRightHeight = 0;
this.list.forEach((item,index) => {
if (elLeftHeight > elRightHeight) {
this.listRight.push(item);
elRightHeight += this.$refs.list[index].$el.clientHeight;
} else {
this.listLeft.push(item);
elLeftHeight += this.$refs.list[index].$el.clientHeight;
}
});
});
過程及原理詳細解析
css
- 使用flex布局設置一個兩欄布局(根據(jù)實際開發(fā)情況可設置多欄布局),每一欄縱向排列
- 單獨設置一個絕對位置的選擇器,使其雖然渲染了,但頁面上不展示
html
- 利用flex布局(也可其他方式,無所謂)形成一個基本的兩欄布局
- 為渲染到頁面但因定位不會展示在頁面的模塊設置ref(也可在js中使用document直接獲取,看你喜好)
js
- 分別定義兩個空數(shù)組用來存儲兩欄要展示的數(shù)據(jù),再將所有數(shù)據(jù)存放在另一個單獨的數(shù)組中,渲染到未展示在頁面上的絕對定位的模塊(為了嚴謹,需將該模塊寬度與兩欄布局的每一欄寬度相同),依次可計算每條數(shù)據(jù)的高度。
- 按照算法思路,設置左右欄高度都為0,遍歷數(shù)據(jù),對左右欄高度做判斷,將數(shù)據(jù)寫入到較低高度的一欄中(相同高度寫入左邊),寫入后將該數(shù)據(jù)的展示高度添加到該欄中
較優(yōu)解:grid布局實現(xiàn)
這種方法不需要對數(shù)據(jù)進行遍歷傳入渲染,瀏覽器自動對內容堆疊排放
首先使用grid布局實現(xiàn)兩欄(或多欄)布局
vue+uniapp的實現(xiàn)
.content {
padding: 10rpx;
display:grid;
grid-auto-rows: 10rpx;
column-gap: 10rpx;
grid-template-columns: 1fr 1fr;
align-items: start;
}
.content-item {
border: 1rpx solid #000;
padding: 10rpx;
}
<view class="content">
<view class="content-item" ref="content" v-for="item in list" :key="item.index">{{ item.content }}</view>
</view>
this.$nextTick(()=>{
this.list.forEach((item, index) => {
this.$refs.content[index].$el.style.gridRowEnd = `span ${Math.ceil(this.$refs.content[index].$el.clientHeight / 5) + 1}`
console.log(this.$refs.content[index].$el.style.gridRowEnd);
})
})

image.png
過程及原理詳細解析
css:
- 使用css的grid布局設定基本兩欄布局(根據(jù)實際開發(fā)情況可設置多欄布局)
- 使用align-items: start設定縱向的排列方式為從上到下依次排列
- 使用grid-auto-rows: 10rpx屬性設置網(wǎng)格每行高度為10rpx
js:
- 使用ref獲取每個內容模塊的高度(我用的vue所以使用的是ref,js也可使用document來獲?。?/li>
- 使用 clientHeight / 5 ,根據(jù)每個模塊的高度去除以css中設置的每個網(wǎng)格高度(示例代碼用的uniapp的單位rpx,clientHeight獲取的是px,10rpx==5px),得到這個模塊縱向占據(jù)網(wǎng)格的數(shù)量,
- 使用js向其添加行內樣式 grid-row-end: span [Number],該屬性設置該模塊縱向占據(jù)的網(wǎng)格數(shù)量,瀏覽器渲染時會將其自動向下堆疊