前言:最近項目好幾個都懟到一起,導致好久沒有更新了。這裏就簡單記錄下這段時間常常要寫的瀑布流列表
純css實現:
- 直接上代碼
<style lang="scss">
.post-list{/* 列表設置,2列;列間距4*/
-webkit-column-count: 2;
-webkit-column-gap:16upx;
padding: 30upx 16upx;
.post-li{
-webkit-column-break-inside: avoid;/* 單個設置*/
}
}
</style>
-
效果:豎向排列,並且在排列中,會盡量使得兩列的高度相近
豎向排列.png - 所以這樣的實現並不能用於列表分頁加載。。。每次加載新頁面,會使得整個列表重排。。。。
js動態排序:
- 還是用最近一直在寫的uni-app寫的,通過獲取元素的高度進行絕對定位
- 還是上代碼(數據)
data(){
return {
mescroll: null, //目前在用的上拉組件(別的組件也一樣,原理基本相似)
upOption:{ //上拉組件配置
page: {
size: 6 // 每頁數據的數量,默認10
},
},
list:[], //列表數據
mark: 0, // 定位
loadingTop: 0, //mescroll數據佔位高度
boxHeight: [] // 計算盒子 2 行的高度
}
}
- 代碼(方法)
- 列表中的每個item爲絕對定位,首先都是top:0;left:0;
- 爲這邊設置爲2列,所以第二列的left:50%;
- 至於每個item邊距,我承認自己很雞賊地用了border(並且設置border-box),具體看下面代碼
- 第一行:top爲0
其他行:算出當前最短列的高度,從而獲得item絕對定位高度(因爲border的緣故,也不需要擔心會和上面的item粘在一起) - 因爲是2列,所以給其中一列加個屬性left=1;在加載時判斷left==1時,添加style:left:50%;
methods:{
/*上拉加載的回調*/
upCallback(mescroll) {
let param = {"pageSize":mescroll.size,"nowPage":mescroll.num}
apiGetForum(param).then(res=>{
if(mescroll.num==1) { //在列表重新加載第一頁時清空相關數據(下拉刷新時,以及tab切換時)
this.list = [];
this.loadingTop = 0;
this.boxHeight=[]
}
this.mark = (mescroll.num-1) * mescroll.size // 每次只計算新加載的數據
if(res.infos) { //新的數據
this.list = this.list.concat(res.infos);
mescroll.endBySize(res.infos.length, res.total)
this.$nextTick(function(){
setTimeout(()=>{ //uni.createSelectorQuery()是異步的,最好setTimeout一下
uni.createSelectorQuery().selectAll('.post-li').boundingClientRect().exec(res => {
let item = res[0];
let len = item.length;
for (let i = this.mark; i < len; i++) {
let height = parseInt(item[i].height); //獲取每個item高度
let boxHeight = height;
if (i < 2) { // 第一列
this.$set(this.list[i], 'top', 0);
this.$set(this.list[i], 'left', i);
this.boxHeight.push(boxHeight);
this.loadingTop = this.boxHeight[0]>this.boxHeight[1]?this.boxHeight[0]:this.boxHeight[1]
} else { //其他列,獲取當前最數組中最小高度和它的索引
let minHeight = this.boxHeight[0];
let boxLen = this.boxHeight.length;
let index = 0;
for (var j = 0; j < boxLen; j++) {
if (minHeight > this.boxHeight[j]) {
minHeight = this.boxHeight[j];
index = j;
}
}
//設置下一行的第一個盒子位置, top值就是最小列的高度
this.$set(this.list[i], 'top', this.boxHeight[index]);
this.$set(this.list[i], 'left', index);
//修改最小列的高度 = 當前自己的高度 + 拼接過來的高度
this.boxHeight[index] = this.boxHeight[index] + boxHeight;
this.loadingTop = this.boxHeight[index];
}
//這裏是爲了圖片加載,在剛獲取到數據時,七牛處理成模糊的圖,只爲列拿到item的高度,排序完成後,圖片改成清晰的
this.$set(this.list[i], 'isLoad', true);
}
});
},120)
})
} else{
mescroll.endBySize(0,0)
}
}).catch(()=>{
mescroll.endErr()
})
},
//獲取圖片
getImg(str,isLoad,type){ //this.$getImgUrl()是封裝的七牛圖片拼接壓縮的方法,不贅述
let arr
let newUrl
if (str.indexOf('[')>-1&&str.length>2) {
arr = JSON.parse(str)
newUrl = this.$getImgUrl(arr[0])
if(isLoad){
if(type==1) { //視頻直接返回
return newUrl
} else { //清晰圖
return this.$getImgUrl(newUrl,300)
}
} else{//模糊的圖,我測試列一下,圖片大小是300字節左右
return this.$getImgUrl(newUrl,10)
}
} else {
return str
}
}
}
- 代碼(上一下我雞賊的css吧),實現列表距離外邊框 8upx; 每個item相距16upx
view{box-sizing: border-box;}
.post-list{
position: relative;
width: 100%;
height: 100%;
border: 8upx solid #f8f8f8;
.post-li{
position: absolute;
left: 0;
width: 50%;
background: #fff;
border: 8upx solid #f8f8f8;
border-radius: 8upx;
&.left{
left: 50%;
}
}
}