vue实现触底加载
触底加载的实现原理
触底加载(无限滚动)的核心是监听滚动事件,判断页面是否滚动到底部。当滚动条接近底部时触发数据加载,通常结合分页接口实现。
监听滚动事件
在Vue中可以通过@scroll事件监听容器滚动,或使用IntersectionObserver API更高效地观察元素可见性。推荐后者,因其性能更好且无需频繁计算滚动位置。
// 使用IntersectionObserver
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
// 触发加载更多
}
});
observer.observe(document.querySelector('#loadMoreTrigger'));
实现基本逻辑
-
数据分页请求 确保后端接口支持分页(如
page和pageSize参数),每次滚动到底部时请求下一页数据。 -
合并新数据 将新获取的数据合并到现有列表中,避免覆盖原有数据。
data() {
return {
list: [],
page: 1,
loading: false,
noMore: false
}
},
methods: {
async loadMore() {
if (this.loading || this.noMore) return;
this.loading = true;
const res = await api.getList({ page: this.page });
this.list = [...this.list, ...res.data];
this.page++;
this.noMore = res.data.length === 0;
this.loading = false;
}
}
优化体验
-
节流处理
避免滚动事件频繁触发,使用lodash.throttle或自定义延迟逻辑。
-
加载状态提示
显示“加载中”或“暂无更多数据”的UI反馈。
<div v-if="loading">加载中...</div>
<div v-if="noMore">没有更多了</div>
完整组件示例
<template>
<div class="container" @scroll="handleScroll">
<div v-for="item in list" :key="item.id">{{ item.name }}</div>
<div v-if="loading">加载中...</div>
<div v-if="noMore">没有更多了</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [],
page: 1,
loading: false,
noMore: false
};
},
mounted() {
this.loadMore();
},
methods: {
handleScroll(e) {
const { scrollTop, clientHeight, scrollHeight } = e.target;
if (scrollHeight - (scrollTop + clientHeight) < 50 && !this.loading) {
this.loadMore();
}
},
async loadMore() {
this.loading = true;
const res = await fetchList(this.page); // 替换为实际API
this.list = [...this.list, ...res.data];
this.page++;
this.noMore = res.data.length < 10; // 假设每页10条
this.loading = false;
}
}
};
</script>
第三方库推荐
若需快速实现,可使用现成库:
- vue-infinite-loading
- vue-virtual-scroller(适用于长列表优化)
安装示例:

npm install vue-infinite-loading
使用方式:
<template>
<InfiniteLoading @infinite="loadMore" />
</template>
注意事项
-
容器高度
确保滚动容器有固定高度且overflow-y: auto。 -
移动端兼容性
某些移动端浏览器可能对滚动事件的支持不同,需额外测试。 -
内存管理
超长列表可能导致性能问题,建议结合虚拟滚动技术优化。






