vue怎么实现滚动加载
Vue 实现滚动加载的方法
滚动加载(无限滚动)是常见的数据加载方式,通过监听滚动事件在用户接近底部时加载更多数据。以下是几种实现方式:

使用原生滚动事件监听
通过监听窗口或容器的滚动事件,计算滚动位置触发加载:

<template>
<div class="scroll-container" @scroll="handleScroll">
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<div v-if="loading">Loading...</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
loading: false,
page: 1
}
},
mounted() {
this.loadData()
},
methods: {
handleScroll(e) {
const { scrollTop, clientHeight, scrollHeight } = e.target
if (scrollHeight - scrollTop - clientHeight < 50 && !this.loading) {
this.loadData()
}
},
async loadData() {
this.loading = true
const newItems = await fetchData(this.page++)
this.items = [...this.items, ...newItems]
this.loading = false
}
}
}
</script>
<style>
.scroll-container {
height: 500px;
overflow-y: auto;
}
</style>
使用 Intersection Observer API
更高效的现代浏览器 API,避免频繁触发滚动事件:
<template>
<div class="scroll-container">
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<div ref="loader" v-if="!finished">{{ loading ? 'Loading...' : '' }}</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
loading: false,
page: 1,
finished: false
}
},
mounted() {
this.initObserver()
this.loadData()
},
methods: {
initObserver() {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && !this.loading && !this.finished) {
this.loadData()
}
})
observer.observe(this.$refs.loader)
},
async loadData() {
this.loading = true
const newItems = await fetchData(this.page++)
if (newItems.length === 0) this.finished = true
this.items = [...this.items, ...newItems]
this.loading = false
}
}
}
</script>
使用第三方库
vue-infinite-loading 等库提供封装好的解决方案:
<template>
<div>
<div v-for="item in items" :key="item.id">{{ item.content }}</div>
<InfiniteLoading @infinite="loadData" />
</div>
</template>
<script>
import InfiniteLoading from 'vue-infinite-loading'
export default {
components: { InfiniteLoading },
data() {
return {
items: [],
page: 1
}
},
methods: {
async loadData($state) {
try {
const newItems = await fetchData(this.page++)
if (newItems.length) {
this.items = [...this.items, ...newItems]
$state.loaded()
} else {
$state.complete()
}
} catch (e) {
$state.error()
}
}
}
}
</script>
性能优化建议
- 添加防抖处理避免频繁触发
- 使用虚拟滚动(如 vue-virtual-scroller)处理大量数据
- 服务端应支持分页查询
- 显示加载状态和错误处理
- 移动端注意滚动体验
以上方法可根据具体需求选择,原生实现适合简单场景,第三方库提供更完整的解决方案。






