vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)
一、思路分析和效果图
用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果。然后针对这几个效果的实现,捋下思路:
根据加载数据的顺序,依次追加标签展示效果;
选择哪种方式实现瀑布流,这里选择绝对定位方式;
关键问题:由于每张图片的宽高不一样,而瀑布流中要求所有图片的宽度一致,高度随宽度等比缩放。而且由于图片的加载是异步延迟。在不知道图片高度的情况下,每个图片所在的item盒子不好绝对定位。因此在渲染页面前先获取所有图片的高度,是解决问题的关键点!这里选择用JS中的Image类,通过预加载图片的方式提前获取图片宽高,另外通过一个临时变量来计算是否所有图片的高度已经得到。当所有的图片高度获取后,开始渲染页面。
页面渲染后,获取所有图片所在的盒子,循环计算盒子的高度,开始设置每个盒子item的绝对定位。
页面渲染时,会出现闪烁的现象。如何解决这个问题呢?这里用了一个动画样式。不过在第一次加载的时候,还是会有一点闪烁的感觉。
然后就是下拉刷新和上拉加载更多的效果,这里用了有赞的vant组件PullRefresh和List这套组合组件来实现。
先看个效果动图:
静态截图:
二、具体实现步骤
2.1、页面结构设计,测试数据准备。
本地准备一个json文件数据,放在项目public文件夹下。注意,本地测试数据必须放在public文件夹下,网络请求时才能请求到数据,这是vue3.x。新增加一个axios依赖包,用来进行网络请求。部分截图,及关键代码:
//数据请求 getDataList(){ this.$axios.get("/json/dataList.json").then((res)=>{ letlist=res.data.data?res.data.data:[]; if(list.length>0){ //从list中取pageSize条数据出来 vartempList=[]; for(leti=0;i0){ lettempIndex=parseInt(Math.random()*1000)%list.length; tempList.push(list[tempIndex]); list.splice(tempIndex,1); } } this.loadImagesHeight(tempList);//模拟预加载图片,获取图片高度 } else{ this.loadImagesHeight(list); } }).catch((res)=>{ console.log("..fail:",res); this.$toast.clear(); this.isLoading=false;//下拉刷新请求完成 this.loading=false;//上拉加载更多请求完成 }) },
2.2、预加载图片,存储图片高度
获取数据后,遍历数据数组,预加载图片,计算图片缩放后的高度,存储起来。同时由于图片加载是异步加载,所以用变量计数,当最后一个图片加载完成后,开始渲染页面。
loadImagesHeight(list){ varcount=0;//用来计数,表示是否所有图片高度已经获取 list.forEach((item,index)=>{ //创建图片对象,加载图片,计算图片高度 varimg=newImage(); img.src=item.cover; img.onload=img.onerror=(e)=>{ count++; if(e.type=='load'){//图片加载成功 //计算图片缩放后的高度:图片原高度/原宽度=缩放后高度/缩放后宽度 list[index].imgHeight=Math.round(img.height*this.boxWidth/img.width); //console.log('index:',index,',loadsuc,imgHeiht:',list[index].imgHeight); } else{//图片加载失败,给一个默认高度50 list[index].imgHeight=50; console.log("index:",index,",加载报错:",e); } //加载完成最后一个图片高度,开始下一步数据处理 if(count==list.length){ this.resolveDataList(list); } } }) },
2.3、渲染页面,设置绝对定位
所有图片通过预加载获取图片高度后,开始渲染页面。然后遍历所有图片所在盒子标签,获取盒子高度,设置每个盒子的绝对定位。
resolveDataList(list){//处理数据 //下拉刷新,清空原数据 if(this.pageIndex<=1){ this.itemCount=0; this.dataList=[]; this.lastRowHeights=[0,0];//存储每列的最后一行高度清0 } if(list.length>=this.pageSize){ this.pageIndex++;//还有下一页 } else{ this.finished=true;//当前tab类型下所有数据已经加载完成 } //合并新老两个数组数据 this.dataList=[...this.dataList,...list]; //判断页面是否有数据 this.haveData=this.dataList.length>0?2:1; this.isLoading=false;//下拉刷新请求完成 this.loading=false;//上拉加载更多请求完成 console.log("...datalist:",this.dataList); console.log("...this.isLoading:",this.isLoading) this.$nextTick(()=>{ setTimeout(()=>{ //渲染完成,计算每个item宽高,设置标签坐标定位 this.setItemElementPosition(); this.isLoading=false;//下拉刷新请求完成 this.loading=false;//上拉加载更多请求完成 },1000) }); }, //获取每个item标签高度,设置item的定位 setItemElementPosition(){ letparentEle=document.getElementById('data-list-box'); letboxEles=parentEle.getElementsByClassName("data-item"); for(leti=this.itemCount;i2.4、其他说明
其他页面中如下拉刷新,和上拉加载更多等功能,使用了有赞的组件库中的PullRefresh和List这一套组合组件。感觉效果挺棒的,使用步骤也简单。另外就是在页面渲染时,会出现页面闪烁的现象,后面使用了一个css动画处理了这个现象,效果好了很多。但是在第一次加载的时候,还是有轻微的闪烁现象。等后面找到更好的方法,再更新。
完整效果DEMO地址:https://github.com/xiaotanit/tan_vue/blob/master/src/views/PageWaterFall.vue
总结
以上所述是小编给大家介绍的vue实现网络图片瀑布流+下拉刷新+上拉加载更多(步骤详解),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。