需求最近几天忙于公司项目的一个新需求。原因是这样的:公司要开发一款偏向社交娱乐的小程序,可以在首页看到用户发的话题帖,每条帖子至少包含一张图片或者一段视频,然后是产品方希望首页能够实现instagram的交互效果,效果图如下:嗯,大致就是这个需求的背景,然后每个post的高度不定,大概500~600px.当我第一次接到这个请求实现思路的时候,其实是有点慌的。毕竟有一段时间没接触小程序了,不知道小程序和文档更新到什么程度了。仔细分析项目需求,大致可以分为两类:交互和性能优化。性能优化因为首页是一个很长的列表,众所周知,一旦页面渲染节点过多,就会卡顿,更何况是小程序,小程序分为逻辑层和渲染层,两者是通过setData联系起来的,所以处理时需要注意两点:setData中的数据量不能太大。我记得好像有大小限制。忘记多少了,懒得去找:clown_face:。你可以在官方文档中找到它;页面可以渲染的帖子数量是有限制的,这里我控制最多渲染25个帖子。处理长列表的优化,官方组件-recycle-view也有对应的组件,不过好像不太符合项目要求,就通过了。虽然没有使用官方组件,但是对于长列表的性能优化在组件文档中有说明。以下是关键点的摘录:核心思想是只渲染屏幕上显示的数据。基本实现是监听滚动事件,重新计算需要渲染的数据,为不需要渲染的数据留一个空的div占位元素。其实就是设置一个变量来控制数据是否可以渲染。如果无法渲染,那么我们将用空视图替换它。需要注意的是,失败的是:空框的高度需要设置为post的高度。这样屏幕就不会闪烁了。针对这种思路,我们可以确定长列表性能优化的解决方案之一:将数据分成二维数组,这样可以限制每次数据setData的数量,数据渲染完成后,获取每组数据占用的总高度,这里的高度是设置数据打乱不渲染时占位框的高度。/***获取已经渲染的组的高度,但是还没有获取到高度*/_getGroupListHeight(){this.data.list.forEach((item,index)=>{if(item.show&&!item.height){constid='XXXXXXXX'//groupidletquery=wx.createSelectorQuery()query.select(id).boundingClientRect(rect=>{this.data.list[index].height=rect.height}).exec();this.getTopicHeight(item.data,index)//获取列表中每个topic的高度,用于计算滑动时的滚动距离}})}上面是一个简单的获取每组高度的代码例如,当该组数据已经渲染完成,但高度未知时,就会获取。增加一个判断步骤的目的是为了防止获取到的组的数据被再次检索,造成不必要的浪费。在获取每组数据的高度时,也会对应的获取组内每条帖子的高度,为后面的仿instagram交互做准备。获取到每组数据的高度后,我们就可以通过监听页面滚动的高度来控制要渲染的数据。需要注意的一点是,我们需要根据这组的数据来渲染上组和下组。两组数据,目的是防止用户快速滑动时白屏的不友好体验。当然你也可以根据自己的需要渲染几组。/***页面滚动*@parame*/onPageScroll(e){//android页面滑动处理(非instagram版)if(!this.data.isIos&&!this.data.scrollBoxInfo.canUseScrollBox){//1.处理当前播放的视频if(this.data.currentPlayingId&&Math.abs(e.scrollTop-this.data.scrollTop)>100){this.selectComponent(this.data.currentPlayingId).pauseVideo()this.data.currentPlayingId=''}//2.处理Andorid渲染的包数据this._dealAndroidScroll(e)//3.处理视频自动播放if(this.timer){clearTimeout(this.timer)}this.timer=setTimeout(()=>{this.data.scrollTop=e.scrollTop//记录当前滚动距离,滑动暂停视频播放时需要this.handleAutoPlay(e)//视频自动播放},300)}}/***Android监控滚动,动态设置组*@param{Object}e*/_dealAndroidScroll(e){letmax_height=0//maximumheightfor(leti=0;i<=this.data.topicScroll.show_index;i++){max_height+=this.data.list[i].height}让min_height=max_height-this.data.list[this.data.topicScroll.show_index].height//最小高度//超出,+1if(e.scrollTop>max_height&&this.data.topicScroll.show_index
