vue移动端实现滚动加载更多和下拉刷新功能,vant-ui的PullRefresh和List组件结合使用的坑
需求,移动端列表页不再是分页实现点击上一页下一页,需要实现滚动到底部自动加载下一页,页面整个下拉的话,就刷新当前页面的数据。需求很简单。我这边引入了vant-ui,实现起来呢,遇到各种问题。网上找了一大圈,发现一个能打的都没有,都有问题。我整个人都不好了。为什么呢?特此先记录一下,我的实现过程。虽然,不是最好的实现方式,但是,目前各种暴力测试,没有发现bug了。总算能用了。测试遇到的问题...
需求,移动端列表页不再是分页实现点击上一页下一页,需要实现滚动到底部自动加载下一页,页面整个下拉的话,就刷新当前页面的数据。
需求很简单。我这边引入了vant-ui,实现起来呢,遇到各种问题。网上找了一大圈,发现一个能打的都没有,都有问题。我整个人都不好了。为什么呢?
特此先记录一下,我的实现过程。虽然,不是最好的实现方式,但是,目前各种暴力测试,没有发现bug了。总算能用了。
测试遇到的问题有哪些呢?下拉刷新,数据突然没有了,页面list空白;加载到第二页,还在加载中,又暴力的进行下拉刷新,导致这个第二页的数据,跑到第一页的数据顶部,再后面又是第二页数据,第三页数据;不说了,测试了很多方法,都不行。这个破玩意,把我折腾的,实在是不轻。
目前的方法,比较稳定了,至少没有这些莫名其妙的bug了。
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<div
v-for="(item, index) in list"
:key="index"
class="item-wrap van-hairline--bottom"
>
<div class="item-name">{{ item.name }}</div>
</div>
</van-list>
</van-pull-refresh>
。。。。。。。。。。
data() {
return {
list: [], // 列表数据
pageIndex: 1, // 当前页码
pageSize: 10, // 分页大小
total: 0, // 查询总条数
loading: false, // 滚动加载中
finished: false, // 滚动加载完成
isLoading: false, // 下拉强制刷新
};
},
list组件,监听的方法是onLoad
, 由loading和finished两个来控制。
PullRefresh组件,由isLoading来控制,监听的方法是onRefresh
分离出获取数据ajax的函数,fetchList
// 获取数据列表
fetchList() {
return new Promise((resolve, reject) => {
let para = {
data: {
confirm: false,
pageIndex: this.pageIndex,
pageSize: this.pageSize,
},
};
temperatureWarningList(para)
.then((res) => {
let result = {
total: res.data.recordTotal,
pageIndex: res.data.pageIndex,
list: res.data.list,
};
resolve(result);
})
.catch((err) => {
reject(err);
});
});
},
onLoad的内容
// 滚动加载更多
onLoad() {
this.loading = true;
this.fetchList().then((res) => {
if (res.list.length < this.pageSize) {
// 数据小于10条,已全部加载完毕finished设置为true
this.finished = true;
}
if (res.list.length === 0) {
// 数据返回为空,表示没有数据了
this.loading = false;
this.finished = true;
}
// fix第二页数据未加载完成就强制下拉刷新,导致上一次的第二页的数据跑到这一次第一页的数据的前面的bug
if (this.pageIndex == res.pageIndex) {
this.pageIndex = res.pageIndex + 1;
this.list = this.list.concat(res.list);
}
this.loading = false;
});
},
onRefresh的内容
// 下拉刷新
onRefresh() {
this.list = [];
this.pageIndex = 1;
this.finished = false;
this.loading = true;
this.onLoad();
this.isLoading = false; // 下拉加载完成,关闭,不然就会有两个显示加载中的转圈圈。list本身就有一个了。啊。好恶心。
},
如果拉动的内容,不是全屏,就需要改写 van-pull-refresh
的样式,用命名空间覆盖或是重写。我的这里是由于自己的样式在vant的样式后面引入,加入scoped也可以生效。如果不能生效,写一个不带scoped的style,然后外面套一层class类名作为命名空间。
<style lang="less" scoped>
.van-pull-refresh {
min-height: calc(100vh - 46px);
}
</style>
如果您有更好的方法,还希望不吝赐教,请收下我的膝盖。
时间紧,目前就这样了。
未来,有更好的解决办法了,再来更新。记录一下。
单纯只想使用onLoad方法
data() {
return {
offset:0,//滚动条与底部距离小于 offset 时触发load事件,默认300
pageNo: 1, // 当前页码
pageSize: 10, // 分页大小
total: 0, // 查询总条数
loading: false, // 滚动加载中
finished: false, // 滚动加载完成
list:[ ],
};
},
<van-list
v-model="loading"
:finished="finished"
:offset="offset"
:immediate-check="false"
finished-text="没有更多了"
@load="onLoad"
>
<p v-for="(item, index) in list" :key="index>{{item.name}}</p>
</vant-list>
getDutyList() {
return new Promise((resolve, reject) => {
let params = {
pageNo: this.pageNo,
pageSize: this.pageSize,
};
this.axios.get(params).then((res) => {
if (res.data.status == 0) {
if (res.data.data.resultData.length > 0) {
let result = {
total: res.data.data.total,
pageNo: res.data.data.pageNo,
data: res.data.data.resultData,
};
resolve(result);
}
}
}).catch((err) => {
reject(err);
});
})
},
// 滚动加载更多
onLoad() {
this.loading = true;
this.getDutyList().then((res) => {
this.list= this.list.concat(res.data);
if (this.list.length>=res.total) {
this.finished = true;
} else {
this.finished = false;
this.pageNo += 1
}
this.loading = false
});
},
注意: :immediate-check="false"
设置关闭后,就需要自己手动触发第一次onLoad方法。手动调用。
更多推荐
所有评论(0)