分页加载时怎么避免重复请求和数据错乱?

晓萌 Dev 阅读 2

我用 Vue 做了个列表,滚动到底部就加载下一页,但有时候快速滚动会触发多次请求,导致数据重复或者顺序错乱。试过加 loading 锁,但好像没完全解决问题。

这是我的加载逻辑:

<template>
  <div @scroll="handleScroll" style="height: 400px; overflow-y: auto">
    <div v-for="item in list" :key="item.id">{{ item.name }}</div>
  </div>
</template>

<script>
export default {
  methods: {
    async handleScroll() {
      if (this.loading) return;
      this.loading = true;
      const res = await fetch(/api/items?page=${this.page++});
      this.list.push(...res.data);
      this.loading = false;
    }
  }
}
</script>
我来解答 赞 0 收藏
二维码
手机扫码查看
1 条解答
FSD-菲菲
你这个情况我遇到过,确实挺烦人的。除了加loading锁,还需要做几个关键处理:

1. 加个防抖,避免滚动事件触发太频繁:
export default {
data() {
return {
debounceTimer: null,
// 其他数据...
}
},
methods: {
async handleScroll() {
clearTimeout(this.debounceTimer)
this.debounceTimer = setTimeout(() => {
if (this.loading) return
// 其他逻辑...
}, 300) // 300ms防抖
}
}
}


2. 要做页码校验,防止并发请求导致page自增混乱:
const currentPage = this.page
const res = await fetch(/api/items?page=${currentPage})
// 检查返回数据是否确实是对应页码的
if (res.page === currentPage) {
this.page++
this.list.push(...res.data)
}


3. 安全提醒:别忘了加错误处理,网络请求可能会失败。建议把loading状态放在finally里:
try {
this.loading = true
// 请求逻辑...
} catch (e) {
console.error('加载失败', e)
// 可以在这里回退page计数
} finally {
this.loading = false
}


另外建议用IntersectionObserver替代scroll事件监听,性能更好也更精确。不过要看你项目浏览器兼容性要求。
点赞
2026-03-05 19:07