vue实现滚动加载更多
Vue 实现滚动加载更多
使用 Intersection Observer API
Intersection Observer API 提供了一种异步观察目标元素与祖先元素或 viewport 的交集变化的方法。这种方法性能较好,适合现代浏览器。
<template>
<div>
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<div ref="loader" class="loader">Loading...</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
page: 1,
isLoading: false
};
},
mounted() {
this.initObserver();
this.loadItems();
},
methods: {
initObserver() {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && !this.isLoading) {
this.loadItems();
}
});
observer.observe(this.$refs.loader);
},
async loadItems() {
this.isLoading = true;
const newItems = await fetch(`/api/items?page=${this.page}`).then(res => res.json());
this.items = [...this.items, ...newItems];
this.page++;
this.isLoading = false;
}
}
};
</script>
<style>
.loader {
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
使用 scroll 事件监听
传统方法通过监听滚动事件实现,适用于需要兼容旧浏览器的场景。

<template>
<div @scroll="handleScroll" style="height: 500px; overflow-y: auto;">
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<div v-if="isLoading" class="loader">Loading...</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
page: 1,
isLoading: false
};
},
mounted() {
this.loadItems();
},
methods: {
handleScroll(e) {
const { scrollTop, clientHeight, scrollHeight } = e.target;
if (scrollHeight - (scrollTop + clientHeight) < 50 && !this.isLoading) {
this.loadItems();
}
},
async loadItems() {
this.isLoading = true;
const newItems = await fetch(`/api/items?page=${this.page}`).then(res => res.json());
this.items = [...this.items, ...newItems];
this.page++;
this.isLoading = false;
}
}
};
</script>
使用第三方库 vue-infinite-loading
vue-infinite-loading 是一个专门为 Vue 设计的无限滚动加载组件,简化了实现过程。

安装:
npm install vue-infinite-loading
使用:
<template>
<div>
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<InfiniteLoading @infinite="loadItems" />
</div>
</template>
<script>
import InfiniteLoading from 'vue-infinite-loading';
export default {
components: { InfiniteLoading },
data() {
return {
items: [],
page: 1
};
},
methods: {
async loadItems($state) {
try {
const newItems = await fetch(`/api/items?page=${this.page}`).then(res => res.json());
if (newItems.length) {
this.items = [...this.items, ...newItems];
this.page++;
$state.loaded();
} else {
$state.complete();
}
} catch (error) {
$state.error();
}
}
}
};
</script>
性能优化建议
- 使用防抖(debounce)技术减少 scroll 事件的触发频率
- 在组件销毁时移除事件监听器或断开 Intersection Observer
- 考虑使用虚拟滚动(如 vue-virtual-scroller)处理大量数据
- 添加错误处理机制和加载状态提示
- 在服务端实现分页查询,避免一次性加载过多数据
以上方法可根据具体需求选择,Intersection Observer API 是现代推荐方案,vue-infinite-loading 则提供了更完整的解决方案。






