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" v-if="!isLoading && hasMore">加载中...</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
page: 1,
isLoading: false,
hasMore: true
}
},
mounted() {
this.initObserver()
this.loadItems()
},
methods: {
initObserver() {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && !this.isLoading && this.hasMore) {
this.loadItems()
}
})
observer.observe(this.$refs.loader)
},
async loadItems() {
this.isLoading = true
try {
const newItems = await fetchItems(this.page)
this.items = [...this.items, ...newItems]
this.page++
this.hasMore = newItems.length > 0
} finally {
this.isLoading = false
}
}
}
}
</script>
使用滚动事件监听
传统方法是通过监听滚动事件来判断是否到达底部。
<template>
<div @scroll="handleScroll" style="overflow-y: auto; height: 500px;">
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<div v-if="isLoading">加载中...</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
page: 1,
isLoading: false,
hasMore: true
}
},
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 < 100 && !this.isLoading && this.hasMore) {
this.loadItems()
}
},
async loadItems() {
this.isLoading = true
try {
const newItems = await fetchItems(this.page)
this.items = [...this.items, ...newItems]
this.page++
this.hasMore = newItems.length > 0
} finally {
this.isLoading = false
}
}
}
}
</script>
使用第三方库
可以使用现成的 Vue 无限滚动库,如 vue-infinite-scroll:

安装:
npm install vue-infinite-scroll
使用:
<template>
<div v-infinite-scroll="loadMore" infinite-scroll-disabled="isLoading" infinite-scroll-distance="10">
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<div v-if="isLoading">加载中...</div>
</div>
</template>
<script>
import infiniteScroll from 'vue-infinite-scroll'
export default {
directives: { infiniteScroll },
data() {
return {
items: [],
page: 1,
isLoading: false,
hasMore: true
}
},
methods: {
async loadMore() {
if (!this.hasMore || this.isLoading) return
this.isLoading = true
try {
const newItems = await fetchItems(this.page)
this.items = [...this.items, ...newItems]
this.page++
this.hasMore = newItems.length > 0
} finally {
this.isLoading = false
}
}
}
}
</script>
性能优化建议
- 使用虚拟滚动(如
vue-virtual-scroller)处理大量数据 - 添加防抖机制避免频繁触发加载
- 在组件销毁时移除事件监听器
- 考虑添加错误处理机制
- 可以显示"没有更多数据"的提示当
hasMore为 false 时
以上方法可以根据具体需求选择使用,Intersection Observer API 是现代浏览器推荐的方式,而第三方库可以快速实现功能。






