小程序瀑布流的实践
前言:最近在工作中,实践了下在微信小程序中实现瀑布流列表(左右两栏,动态图文)
,最终的效果还不错,所以在此记录,仅供有需要的人参考。
最终的效果:
补充说明的是,要做瀑布流,最好是可以知道图片的高度,由接口下发,来提前占位,否则,即使是原生app,也会因为图片的加载闪屏使得不好的用户体验。在小程序中,没有原生app的流式layout控件,所以不知道图片宽高的情况下,只能减少每一页的page_size,在加载完图片之后,再计算插入的位置(对产品来说,这可能是一个不可接受的漫长过程)
尝试过的小程序瀑布流实现方式
1.左右两列判断奇偶性渲染
//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>
说明 | 优点 | 缺点 |
---|---|---|
左右列重复wx:for 渲染数据,根据index索引的奇偶性来wx:if | 简单 | 1.重复for循环。2.如果每个item高度相差较大,很容易造成左右矮的那一栏是部分空白的 |
或许京东购物小程序-首页就是这样做的?(不确定)
2.绝对定位
这个方式可能就是目前pc端的实现方式,原理都一样。但是在小程序中,有以下几个需要解决的问题
- 如果列表是动态图文,即使知道图片宽高,如何获取文字内容区域的高度?
- 安卓下实验过会出现白屏,卡顿等性能问题(这个问题导致直接放弃了这个做法)
3.左右两列计算插入渲染
//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)=>{ //每个item的高度=图片宽高+内容区域 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(){ //文字内容区域高度固定,直接返回 //不固定,做数据映射,例如10个字一行,行高按照设计稿,做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>
说明 | 优点 | 缺点 |
---|---|---|
下面↓↓↓ | 性能好,实现的效果好 | (⊙o⊙)… |
- 每次数据加载回来,例如一次15条,做遍历
注意下面的操作都必须是一个同步获取的过程,需要异步获取的都要async await,如果需要异步获取的数据多,例如图片,那就是一个耗时操作
。 - 获取图片宽高与文字高度。如果不知道图片宽高,就要使用wx.getImageInfo(需要域名的配置)。如果想随便哪找一张图都能瀑布流,那就需要额外的操作,先将图片列表setData去渲染,设置样式为display:none,那它就不会显示,但是会加载图片,通过image bindload,拿到所有图片宽高后,匹配url做一个mapping,一一对应图片和宽高。
- 文字内容区域,如果不是固定高度。那我们根据接口返回的字符长度做一个大概的高度映射就行了,例如10个字一行。
可能有小概率会影响我们的计算,这个问题是存在的且可以接受的
。而且在第4步操作之后,不会影响下一轮。 - 最后,每次setData渲染完之后,我们再通过
createSelectorQuery
获取左右两栏的真实高度,更新一下,为下一次渲染准备
可以看下小程序
附近的餐厅
,效果很好,他的图片宽高是服务器返回的,文字内容区域是固定的(标题只有几个字,也是两行)
结论
目前来说,第三种方案的实现效果最好,也是我们正在线上使用的方式,推荐使用。
相关文章
小程序movable-view拖动排序这里
原文地址:https://segmentfault.com/a/1190000022415428
相关推荐
-
前端玩Rust(持续更新…) javascript/jquery
2020-5-26
-
面试官问你基本类型时他想知道什么 javascript/jquery
2019-4-14
-
如何在Git提交大小写敏感的文件 javascript/jquery
2020-5-27
-
茄子算法每日N题之LeetCode25K个一组翻转链表 javascript/jquery
2020-5-26
-
手摸手教你用 js 写一个 js 解释器 javascript/jquery
2019-5-3
-
JS基础篇–sort()方法的用法,参数以及排序原理 javascript/jquery
2018-10-10
-
Laravel 7 的简单隐式路由模型绑定 javascript/jquery
2020-6-26
-
【译】10个帮助你捕获更多Bug的TypeScript建议 javascript/jquery
2020-5-18
-
精读《useRef 与 createRef 的区别》 javascript/jquery
2020-5-26
-
一个还算实用的分页组件:xy-pagination javascript/jquery
2019-9-1