前言:最近在工作中,實(shí)踐了下在 微信
小程序中實(shí)現(xiàn)瀑布流列表(左右兩欄,動(dòng)態(tài)圖文)
,最終的效果還不錯(cuò),所以在此記錄,僅供有需要的人參考。
最終的效果:
補(bǔ)充說明的是,要做瀑布流,最好是可以知道圖片的高度,由接口下發(fā),來提前占位,否則,即使是原生app,也會(huì)因?yàn)閳D片的加載閃屏使得不好的用戶體驗(yàn)。在小程序中,沒有原生app的流式layout控件,所以不知道圖片寬高的情況下,只能減少每一頁的page_size,在加載完圖片之后,再計(jì)算插入的位置(對(duì)產(chǎn)品來說,這可能是一個(gè)不可接受的漫長過程)
//demo.js
Page({
data:{
renderLists:[]
},
fetchData(){
request(url,params).then(res=>{
const PreData=this.data.renderLists
this.setData({
renderLists:PreData.concat(res)
})
})
}
})
//demo.wxml
<view class="waterfall">
<view class="waterfall__left">
<your-compoent
wx:for="{{renderLists}}"
wx:key="id"
wx:if="{{index % 2 === 0}}"
/>
</view>
<view class="waterfall__right">
<your-compoent
wx:for="{{renderLists}}"
wx:key="id"
wx:if="{{index % 2 === 1}}"
/>
</view>
</view>
說明 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
左右列重復(fù)wx:for 渲染數(shù)據(jù),根據(jù)index索引的奇偶性來wx:if | 簡單 | 1.重復(fù)for循環(huán)。2.如果每個(gè)item高度相差較大,很容易造成左右矮的那一欄是部分空白的 |
或許京東購物小程序-首頁就是這樣做的?(不確定)
這個(gè)方式可能就是目前pc端的實(shí)現(xiàn)方式,原理都一樣。但是在小程序中,有以下幾個(gè)需要解決的問題
//demo.js
Page({
data:{
leftLists:[],
rightLists:[]
},
onLoad(){
this.leftHeight=0
this.rightHeight=0
},
fetchData(){
request(url,params).then(res=>{
this.generate(res)
})
},
generate(list){
let leftList=[],rightList=[]
list.map(async (item)=>{
//每個(gè)item的高度=圖片寬高+內(nèi)容區(qū)域
const itemHeight=getImageHeight(item)+getContentHeight(item)+gap
this.leftHeight>this.rightHeight?rightList.push[item]:leftList.push(item)
})
this.render({leftList,rightList})
},
getImageHeight(){
//如果知道圖片寬高,就return item.height
//如果不知道,wx.getImageInfo(需要配合域名)或者通過display:"node" image 然后 bindload。
},
getContentHeight(){
//文字內(nèi)容區(qū)域高度固定,直接返回
//不固定,做數(shù)據(jù)映射,例如10個(gè)字一行,行高按照設(shè)計(jì)稿,做rpxToPx返回
},
render(params){
const {leftList,rightList}=params
const preLeft=this.data.leftList;
const preRight=this.data.rightList
this.setData({
leftList:preLeft.concat(leftList),
rightList:preRight.concat(rightList)
},()=>{
const query = this.createSelectorQuery();
query.select('.wrapper__left').boundingClientRect();
query.select('.wrapper__right').boundingClientRect();
query.exec((res) => {
this.leftHeight = res[0].height;
this.rightHeight = res[1].height;
});
})
}
})
//demo.wxml
<view class="waterfall">
<view class="waterfall__left">
<your-compoent
wx:for="{{leftLists}}"
wx:key="id"
/>
</view>
<view class="waterfall__right">
<your-compoent
wx:for="{{rightLists}}"
wx:key="id"
/>
</view>
</view>
說明 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
下面↓↓↓ | 性能好,實(shí)現(xiàn)的效果好 | (⊙o⊙)… |
注意下面的操作都必須是一個(gè)同步獲取的過程,需要異步獲取的都要async await,如果需要異步獲取的數(shù)據(jù)多,例如圖片,那就是一個(gè)耗時(shí)操作
可能有小概率會(huì)影響我們的計(jì)算,這個(gè)問題是存在的且可以接受的
createSelectorQuery
可以看下小程序 附近的餐廳
,效果很好,他的圖片寬高是服務(wù)器返回的,文字內(nèi)容區(qū)域是固定的(標(biāo)題只有幾個(gè)字,也是兩行)
目前來說,第三種方案的實(shí)現(xiàn)效果最好,也是我們正在線上使用的方式,推薦使用。
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)