vue实现下拉加载
实现下拉加载的基本思路
下拉加载通常通过监听滚动事件,判断是否滚动到页面底部来触发数据加载。Vue中可以通过结合v-infinite-scroll指令或手动监听滚动事件实现。

使用v-infinite-scroll指令(Element UI)
安装Element UI后,可以直接使用v-infinite-scroll指令简化实现:

<template>
<div
v-infinite-scroll="loadMore"
infinite-scroll-disabled="busy"
infinite-scroll-distance="10"
>
<div v-for="item in list" :key="item.id">{{ item.content }}</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [],
page: 1,
busy: false
}
},
methods: {
async loadMore() {
this.busy = true;
const newData = await fetchData(this.page++);
this.list = [...this.list, ...newData];
this.busy = false;
}
}
}
</script>
手动实现滚动监听
如果没有使用Element UI,可以手动实现滚动监听:
<template>
<div class="scroll-container" @scroll="handleScroll">
<div v-for="item in list" :key="item.id">{{ item.content }}</div>
<div v-if="loading">加载中...</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [],
page: 1,
loading: false,
noMoreData: false
}
},
methods: {
handleScroll(e) {
const { scrollTop, clientHeight, scrollHeight } = e.target;
const isBottom = scrollTop + clientHeight >= scrollHeight - 10;
if (isBottom && !this.loading && !this.noMoreData) {
this.loadMore();
}
},
async loadMore() {
this.loading = true;
const newData = await fetchData(this.page++);
if (newData.length === 0) {
this.noMoreData = true;
} else {
this.list = [...this.list, ...newData];
}
this.loading = false;
}
},
mounted() {
this.loadMore();
}
}
</script>
<style>
.scroll-container {
height: 300px;
overflow-y: auto;
}
</style>
使用Intersection Observer API
现代浏览器支持Intersection Observer API,性能优于滚动事件监听:
<template>
<div class="scroll-container">
<div v-for="item in list" :key="item.id">{{ item.content }}</div>
<div ref="loader" v-if="!noMoreData">加载中...</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [],
page: 1,
loading: false,
noMoreData: false,
observer: null
}
},
methods: {
async loadMore() {
this.loading = true;
const newData = await fetchData(this.page++);
if (newData.length === 0) {
this.noMoreData = true;
this.observer.disconnect();
} else {
this.list = [...this.list, ...newData];
}
this.loading = false;
}
},
mounted() {
this.observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting && !this.loading) {
this.loadMore();
}
});
this.observer.observe(this.$refs.loader);
this.loadMore();
},
beforeDestroy() {
this.observer.disconnect();
}
}
</script>
注意事项
- 节流处理:频繁的滚动事件可能导致性能问题,建议添加节流逻辑
- 加载状态:需要明确区分加载中/加载完成/无更多数据三种状态
- 错误处理:网络请求需要添加错误处理逻辑
- 移动端适配:移动端需要考虑touch事件和滚动行为差异
示例数据获取函数
async function fetchData(page) {
// 模拟API请求
return new Promise(resolve => {
setTimeout(() => {
const newData = Array(10).fill(0).map((_, i) => ({
id: page * 10 + i,
content: `项目 ${page * 10 + i}`
}));
resolve(newData);
}, 500);
});
}






