基于 Vue 3 实现无限滚动翻页组件

简介

无限滚动是现代网页应用中常见的交互模式,用户在滚动到页面底部时自动加载更多内容。今天我们将使用 Vue 3 的组合式 API 来实现一个可复用的无限滚动组件。

核心功能

  • 监听滚动事件
  • 判断是否滚动到底部
  • 触发加载更多数据
  • 支持加载状态显示
  • 支持错误处理

代码实现

1. 组件结构

首先创建一个 InfiniteScroll.vue 文件:

vue:src/components/InfiniteScroll.vue 复制代码
<template>
  <div class="infinite-scroll-container" ref="containerRef">
    <slot></slot>
    <div class="loading-status">
      <div v-if="loading" class="loading">加载中...</div>
      <div v-if="error" class="error">{{ error }}</div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  distance: {
    type: Number,
    default: 100
  }
})

const emit = defineEmits(['load-more'])

const containerRef = ref(null)
const loading = ref(false)
const error = ref(null)

// 检查是否滚动到底部
const isBottom = () => {
  const container = containerRef.value
  return container.scrollHeight - container.scrollTop - container.clientHeight < props.distance
}

// 处理滚动事件
const handleScroll = async () => {
  if (loading.value || error.value) return
  
  if (isBottom()) {
    try {
      loading.value = true
      await emit('load-more')
      loading.value = false
      error.value = null
    } catch (err) {
      error.value = err.message
      loading.value = false
    }
  }
}

onMounted(() => {
  containerRef.value.addEventListener('scroll', handleScroll)
})

onUnmounted(() => {
  containerRef.value.removeEventListener('scroll', handleScroll)
})
</script>

<style scoped>
.infinite-scroll-container {
  height: 100%;
  overflow-y: auto;
}

.loading-status {
  padding: 1rem;
  text-align: center;
}

.loading {
  color: #666;
}

.error {
  color: #ff4444;
}
</style>

2. 使用示例

vue:src/App.vue 复制代码
<template>
  <div class="app">
    <infinite-scroll @load-more="loadMore">
      <div v-for="item in items" :key="item.id" class="item">
        {{ item.content }}
      </div>
    </infinite-scroll>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import InfiniteScroll from './components/InfiniteScroll.vue'

const items = ref([])
const page = ref(1)

const loadMore = async () => {
  // 模拟 API 请求
  const newItems = await fetchData(page.value)
  items.value.push(...newItems)
  page.value++
}

// 模拟数据获取
const fetchData = (page) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(Array.from({ length: 10 }, (_, i) => ({
        id: page * 10 + i,
        content: `Item ${page * 10 + i}`
      })))
    }, 1000)
  })
}
</script>

<style>
.app {
  height: 100vh;
}

.item {
  padding: 20px;
  border-bottom: 1px solid #eee;
}
</style>

关键实现细节

1. 滚动检测

使用 scrollHeightscrollTopclientHeight 来判断是否滚动到底部:

  • scrollHeight: 内容总高度
  • scrollTop: 已滚动距离
  • clientHeight: 可视区域高度

2. 防抖处理

在实际应用中,建议对 handleScroll 函数进行防抖处理,避免频繁触发:

javascript 复制代码
import { debounce } from 'lodash'

const handleScroll = debounce(async () => {
  // 滚动处理逻辑
}, 200)

3. 错误处理

组件内置了简单的错误处理机制,当加载失败时会显示错误信息,并暂停后续加载。

组件特点

  1. 使用 Vue 3 组合式 API,代码更清晰
  2. 支持自定义触发距离
  3. 内置加载状态和错误处理
  4. 可通过插槽自定义内容

使用注意事项

  1. 确保父容器设置了固定高度
  2. 合理设置触发距离(distance)
  3. 处理好数据加载的异常情况
  4. 考虑是否需要添加数据加载完成的判断

总结

这个无限滚动组件封装了常用的滚动加载功能,可以方便地集成到各种列表场景中。通过 Vue 3 的组合式 API,我们能够更清晰地组织代码逻辑,提供更好的可维护性。

相关推荐
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅12 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅12 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端
爱敲代码的小鱼13 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax