1、需求背景
一个页面展示从列表请求到的数据,向上滑动时发送请求接口下一页数据,一直往上滑动可以一直请求数据,直到滑动到最后一页。
2、技术路径
3、不依赖vant组件实现
展示内容,一进入页面加载数据,如果数据还没请求到显示"数据加载中..."的提示,加载到数据后展示数据,如果数据为空展示"暂无内容,请稍后查看"的提示,加载到数据底部时在数据后面显示"暂无更多内容..."的提示。
index.vue
<div class="main" ref="main">
<div v-for="item in dataLists" :key="item.id">
{{ item.content }}
</div>
<div v-if="loading" ref="loading">
数据加载中...
</div>
<div v-if="!loading && dataLists.length === 0">
暂无内容,请稍后查看
</div>
<div v-if="latestId == '-1' && dataLists.length !== 0">
暂无更多内容...
</div>
</div>
样式,允许超过页面的部分可以滚动
index.less
.main {
width: 100%;
height: 100vh;
overflow-y: auto;
}
数据处理逻辑 ,在页面创建的时候就从接口获取数据,监听滚动事件,页面翻页接口是根据前一页的最后一个id来请求下一页数据,当最后一页数据为空时,把最后一个id置为"-1"结束下一次请求。
监听页面滚动,页面容器 scrollTop+clientHeight >= scrollHeight时请求下一页。
index.js
export default {
data() {
return {
dataLists: [],
loading: false,
}
},
created() {
this.getList();
},
mounted() {
const scrollContainer = this.$refs.main;
scrollContainer.addEventListener("scroll", this.handleScroll);
},
beforeDestroy() {
const scrollContainer = this.$refs.main;
scrollContainer.removeEventListener("scroll", this.handleScroll);
},
methods: {
//从接口获取数据
getList(params) {
this.loading = true;
return baseApi.getList({
name: "接口名",
data: params
})
.then((res) => {
if (res.data.list.length) {
this.latestId = res.data.list[res.data.list.length - 1].id;
this.dataLists = res.data.list
} else {
this.loading = false;
this.latestId = "-1";
}
})
.catch((err) => {
if (this.$refs.loading) {
this.$refs.loading.innerText = "数据异常,暂时无法显示~";
}
});
},
// 页面滚动
handleScroll() {
const mainContainer = this.$refs.main;
const scrollHeight = mainContainer.scrollHeight;
const clientHeight = mainContainer.clientHeight;
const scrollTop = mainContainer.scrollTop;
if (scrollTop + clientHeight >= scrollHeight - 100) {//给100px高度,滑到底部提前加载数据
if (this.latestId != "-1" && this.loading == false) {
this.getList(参数);
}
}
if (scrollTop < -100) {
if (this.loading == false) {
this.dataLists = [];
this.latestId = "";
this.getList(参数);
}
}
},
}
}
4、使用vant-list组件实现
安装并导入依赖 npm i vant
main.js
import { createApp } from 'vue';
import 'vant/lib/index.css'
import { List } from 'vant';
const app = createApp(App)
app.use(List)
app.mount("#app")
页面元素 ,使用vant-list组件,通过loading和finished两个变量控制加载状态,当组件滚动到底部的时候,会触发load事件并将loading设置成true。此时可以发起异步请求并更新数据,更新完毕后将loading设置为false。若数据全部加载完毕,则将finished设置为true。
列表数据加载失败,将error设置为true即可显示错误提示,用户点击错误提示提示会重新触发load事件。
index.vue
<div class="main" ref="main">
<van-list :loading="loading" loading-text="数据加载中..." :finished="finished" finished-text="暂无更多内容..." :error="error" error-text="暂无内容,请稍后查看" @load="onLoad()">
<div v-for="item in dataLists" :key="item.id" >
{{ item.content }}
</div>
</van-list>
</div>
样式
index.less
.main {
width: 100%;
height: 100vh;
overflow-y: auto;
}
逻辑处理
index.js
export default {
data() {
return {
dataLists: [],
loading: false,
finished: false,
error: false,
}
},
created() {
this.getList();
},
methods: {
onLoad() {
this.loading = true
this.getDataListInfo(参数);
},
//从接口获取数据
getList(params) {
this.loading = true;
return baseApi.getList({
name: "接口名",
data: params,
})
.then((res) => {
this.loading = false;
if (res.data.list.length) {
this.latestId = res.data.list[res.data.list.length - 1].id;
this.dataLists = res.data.list
} else {
this.finished = true;
this.latestId = "-1";
}
})
.catch((err) => {
this.loading = false;
this.error = true;
});
},
}
}