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

一、思路分析和效果图

用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果。然后针对这几个效果的实现,捋下思路:

根据加载数据的顺序,依次追加标签展示效果;

选择哪种方式实现瀑布流,这里选择绝对定位方式;

关键问题:由于每张图片的宽高不一样,而瀑布流中要求所有图片的宽度一致,高度随宽度等比缩放。而且由于图片的加载是异步延迟。在不知道图片高度的情况下,每个图片所在的item盒子不好绝对定位。因此在渲染页面前先获取所有图片的高度,是解决问题的关键点!这里选择用js中的image类,通过预加载图片的方式提前获取图片宽高,另外通过一个临时变量来计算是否所有图片的高度已经得到。当所有的图片高度获取后,开始渲染页面。

页面渲染后,获取所有图片所在的盒子,循环计算盒子的高度,开始设置每个盒子item的绝对定位。

页面渲染时,会出现闪烁的现象。如何解决这个问题呢?这里用了一个动画样式。不过在第一次加载的时候,还是会有一点闪烁的感觉。

然后就是下拉刷新和上拉加载更多的效果,这里用了有赞的vant组件pullrefresh和list这套组合组件来实现。

先看个效果动图:

c05e6ea0161721130371a681132a2cb7.gif

静态截图:

34b51015f24e873c62eeba56a60fec42.png

二、具体实现步骤

2.1、页面结构设计,测试数据准备。

本地准备一个json文件数据,放在项目public文件夹下。注意,本地测试数据必须放在public文件夹下,网络请求时才能请求到数据,这是vue3.x。新增加一个axios依赖包,用来进行网络请求。部分截图,及关键代码:

3c076ee7764e04af4efaf13136bf0184.png

//数据请求

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动画处理了这个现象,效果好了很多。但是在第一次加载的时候,还是有轻微的闪烁现象。等后面找到更好的方法,再更新。

总结

以上所述是小编给大家介绍的vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解),希望对大家有所帮助

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值