开发预览 更新于 2026-05-10

InfiniteScroll 无限滚动

滚动到底部时自动触发加载下一页,基于 IntersectionObserver。

基础用法

把列表放在组件 slot 内即可;当组件底部的 sentinel 进入视口(提前 threshold 像素)时触发 loadloading 抑制重复触发,finished 显示「没有更多了」。

背景
  • 第 1 项
  • 第 2 项
  • 第 3 项
  • 第 4 项
  • 第 5 项
  • 第 6 项
  • 第 7 项
  • 第 8 项
  • 第 9 项
  • 第 10 项
  • 第 11 项
  • 第 12 项
<script setup lang="ts">
import { ref } from 'vue';
import { CfInfiniteScroll } from '@chufix-design/vue';

const items = ref<number[]>(Array.from({ length: 12 }, (_, i) => i + 1));
const loading = ref(false);
const finished = ref(false);

function loadMore() {
  if (loading.value || finished.value) return;
  loading.value = true;
  setTimeout(() => {
    const start = items.value.length + 1;
    items.value.push(...Array.from({ length: 12 }, (_, i) => start + i));
    loading.value = false;
    if (items.value.length >= 60) finished.value = true;
  }, 600);
}
</script>

<template>
  <div style="height: 280px; overflow-y: auto; border: 1px solid var(--line-1); border-radius: 8px; padding: 8px;">
    <CfInfiniteScroll
      :loading="loading"
      :finished="finished"
      :threshold="80"
      @load="loadMore"
    >
      <ul style="margin: 0; padding: 0; list-style: none; display: grid; gap: 4px;">
        <li
          v-for="i in items"
          :key="i"
          style="padding: 8px 12px; background: var(--bg-2); border-radius: 4px;"
        >第 {{ i }} 项</li>
      </ul>
    </CfInfiniteScroll>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfInfiniteScroll } from '@chufix-design/vue';

const items = ref<number[]>(Array.from({ length: 12 }, (_, i) => i + 1));
const loading = ref(false);
const finished = ref(false);

function loadMore() {
  if (loading.value || finished.value) return;
  loading.value = true;
  setTimeout(() => {
    const start = items.value.length + 1;
    items.value.push(...Array.from({ length: 12 }, (_, i) => start + i));
    loading.value = false;
    if (items.value.length >= 60) finished.value = true;
  }, 600);
}
</script>

<template>
  <div style="height: 280px; overflow-y: auto; border: 1px solid var(--line-1); border-radius: 8px; padding: 8px;">
    <CfInfiniteScroll
      :loading="loading"
      :finished="finished"
      :threshold="80"
      @load="loadMore"
    >
      <ul style="margin: 0; padding: 0; list-style: none; display: grid; gap: 4px;">
        <li
          v-for="i in items"
          :key="i"
          style="padding: 8px 12px; background: var(--bg-2); border-radius: 4px;"
        >第 {{ i }} 项</li>
      </ul>
    </CfInfiniteScroll>
  </div>
</template>
<CfInfiniteScroll loading={loading} finished={finished} onLoad={loadMore}>
<ul>...</ul>
</CfInfiniteScroll>
<CfInfiniteScroll loading={loading} finished={finished} onLoad={loadMore}>
<ul>...</ul>
</CfInfiniteScroll>

API

属性类型默认值说明
loadingbooleanfalse加载中,期间不再触发 load
finishedbooleanfalse已无更多数据
thresholdnumber100sentinel 进入视口前 N 像素就触发(rootMargin)

事件:onLoad() —— 应在事件中加载下一批数据。

Slot(Vue):loading / finished 自定义底部提示文案。

反馈与讨论

InfiniteScroll 无限滚动 的讨论

0
0 / 600
一键发送
正在加载评论...