侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)

前端  /  管理员 发布于 3年前   179

一、思路分析和效果图

  用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)=>{  let list = res.data.data ? res.data.data: [];  if (list.length > 0){  //从list中取pageSize条数据出来  var tempList = [];  for (let i = 0; i < this.pageSize; i++){   if (list.length > 0){   let tempIndex = 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){  var count = 0; //用来计数,表示是否所有图片高度已经获取  list.forEach((item, index)=>{   //创建图片对象,加载图片,计算图片高度   var img = new Image();   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, ', load suc, 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(){  let parentEle = document.getElementById('data-list-box');  let boxEles = parentEle.getElementsByClassName("data-item");  for (let i = this.itemCount; i < boxEles.length; i++){   let tempEle = boxEles[i];   //上一个标签最小高度的列索引   let curColIndex = this.getMinHeightIndex(this.lastRowHeights);   let boxTop = this.lastRowHeights[curColIndex] + this.boxMargin;   let boxLeft = curColIndex * (this.boxWidth + this.boxMargin) + this.boxMargin;   tempEle.style.left = boxLeft + 'px';   tempEle.style.top = boxTop + 'px';   this.lastRowHeights[curColIndex] = boxTop + tempEle.offsetHeight;   // console.log('i = ', i, ', boxTop: ', boxTop, ', eleHeight: ', tempEle.offsetHeight);  }  this.itemCount = boxEles.length;  //修改父级标签的高度  let maxHeight = Math.max.apply(null, this.lastRowHeights);  parentEle.style.height = maxHeight + 'px';  this.$toast.clear();  console.log("...boxEles: ", boxEles.length, ", maxH: ", maxHeight);  },

2.4、其他说明

  其他页面中如下拉刷新,和上拉加载更多等功能,使用了有赞的组件库中的PullRefresh 和 List这一套组合组件。感觉效果挺棒的,使用步骤也简单。另外就是在页面渲染时,会出现页面闪烁的现象,后面使用了一个css动画处理了这个现象,效果好了很多。但是在第一次加载的时候,还是有轻微的闪烁现象。等后面找到更好的方法,再更新。

完整效果DEMO地址:https://github.com/xiaotanit/tan_vue/blob/master/src/views/PageWaterFall.vue

总结

以上所述是小编给大家介绍的vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

您可能感兴趣的文章:

  • 如何通过shell脚本自动生成vue文件详解
  • 解决vue中修改export default中脚本报一大堆错的问题
  • vue页面加载时的进度条功能(实例代码)
  • 解决vue项目中页面调用数据 在数据加载完毕之前出现undefined问题
  • 在vue中使用防抖和节流,防止重复点击或重复上拉加载实例
  • 详解vue页面首次加载缓慢原因及解决方案
  • 使用Vue实现调用接口加载页面初始数据
  • vue+element树组件 实现树懒加载的过程详解
  • mpvue 页面预加载新增preLoad生命周期的两种方式
  • vue如何实现动态加载脚本


  • 上一条:
    HTML meta 详解
    下一条:
    div怎样在object上面显示不被object动画给遮挡
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在js中使用URL类用来解析处理URL的示例代码(0个评论)
    • js中动画事件:requestAnimationFrame、transitionend、animation...(0个评论)
    • 在js中mouseover和 mouseenter的区别浅析(0个评论)
    • uniapp调用手机实现打电话录音功能示例代码(0个评论)
    • 在uniapp开发微信小程序中图片大小显示不正常解决方法(0个评论)
    • 近期文章
    • 在laravel框架中的5个HTTP客户端技巧分享(0个评论)
    • 在go语言中使用FFmpeg库实现PCM音频文件编码为mp3格式文件流程步骤(0个评论)
    • gopacket免安装Pcap实现驱动层流量抓包流程步骤(0个评论)
    • 在laravel项目中实现密码强度验证功能推荐扩展包:password-strength(0个评论)
    • 在go语言中用filepath.Match()函数以通配符模式匹配字符串示例(0个评论)
    • Laravel Response Classes 响应类使用优化浅析(0个评论)
    • mysql中sql_mode的各模式浅析(0个评论)
    • 百度文心一言今天发布,个人第一批内测体验记录,不好别打我(0个评论)
    • 嘿加密世界让我们谈谈在共识中将中本聪主流化(0个评论)
    • 在go语言中寻找两个切片或数组中的相同元素/共同点/交集并集示例代码(0个评论)
    • 近期评论
    • 博主 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 @ xiaoB 你只管努力,剩下的叫给天意;天若有情天亦老,..
    • xiaoB 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 会不会春节放假后又阳一次?..
    • BUG4 在

      你翻墙过吗?国内使用vpn翻墙可能会被网警抓,你需了解的事中评论 不是吧?..
    • 博主 在

      go语言+beego框架中获取get,post请求的所有参数中评论 @ t1  直接在router.go文件中配就ok..
    • Jade 在

      如何在MySQL查询中获得当月记录中评论 Dear zongscan.com team, We can skyroc..
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客