vue实现自动滚动加载
Vue 实现自动滚动加载
使用 Intersection Observer API
Intersection Observer API 可以监听元素是否进入视口,适合实现滚动加载。以下是一个基本实现示例:
<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.loadItems();
this.setupObserver();
},
methods: {
setupObserver() {
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 this.fetchItems(this.page);
this.items = [...this.items, ...newItems];
this.page++;
this.isLoading = false;
},
fetchItems(page) {
// 替换为实际API调用
return new Promise(resolve => {
setTimeout(() => {
resolve(Array(10).fill().map((_, i) => ({
id: (page - 1) * 10 + i,
content: `Item ${(page - 1) * 10 + i}`
})));
}, 500);
});
}
}
}
</script>
使用窗口滚动事件
对于需要兼容旧浏览器的场景,可以使用窗口滚动事件:

<template>
<div>
<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,
scrollThreshold: 200
}
},
mounted() {
this.loadItems();
window.addEventListener('scroll', this.handleScroll);
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll);
},
methods: {
handleScroll() {
const scrollPosition = window.innerHeight + window.scrollY;
const pageHeight = document.body.offsetHeight;
if (pageHeight - scrollPosition < this.scrollThreshold && !this.isLoading) {
this.loadItems();
}
},
async loadItems() {
this.isLoading = true;
const newItems = await this.fetchItems(this.page);
this.items = [...this.items, ...newItems];
this.page++;
this.isLoading = false;
},
fetchItems(page) {
// 同上
}
}
}
</script>
使用第三方库
对于更复杂的需求,可以考虑使用专门处理无限滚动的库:
-
安装 vue-infinite-loading:

npm install vue-infinite-loading -
使用示例:
<template> <div> <div v-for="item in items" :key="item.id">{{ item.content }}</div> <InfiniteLoading @infinite="loadItems" /> </div> </template>
export default { components: { InfiniteLoading }, data() { return { items: [], page: 1 } }, methods: { async loadItems($state) { try { const newItems = await this.fetchItems(this.page); if (newItems.length) { this.items = [...this.items, ...newItems]; this.page++; $state.loaded(); } else { $state.complete(); } } catch (error) { $state.error(); } }, fetchItems(page) { // 同上 } } }
```性能优化建议
- 对长列表使用虚拟滚动技术(如 vue-virtual-scroller)
- 在组件销毁时移除事件监听器
- 添加防抖机制防止频繁触发加载
- 实现错误处理和重试机制
- 考虑添加无更多数据的提示
以上方法可以根据具体项目需求选择或组合使用,Intersection Observer API 是现代浏览器推荐的方式,而窗口滚动事件则具有更好的兼容性。






