SwGallery

SwGallery 是不滾動、換行鋪成等高網格的封面卡容器,與 SwRail(橫滾橫排)互補。它只管佈局與取數節奏——卡片一切視覺(封面 / 角標 / 評分 / 集數)由 #default 作用域插槽業務渲染(通常放 SwImage),影 / 漫 / 小說封面對元件無差別。

海報牆:minItemWidth 自適應列數 + 按鈕載入更多(剩餘計數)

加载中...

列數控制(二選一)

模式寫法適用
定卡寬自適應(預設):min-item-width="180"海報牆:視窗縮放列數跟著變(CSS Grid auto-fill + minmax)
鎖定列數:columns="3" 或 :columns="{ mobile: 1, tablet: 2, desktop: 3 }"設計稿明確列數、超寬螢幕不許變(斷點對齊 framework:mobile <768 / desktop ≥1024,缺檔就近回退)

兩者純 CSS 實作(media query + CSS 變數),零 JS、SSR 安全。columns 傳了即覆蓋 minItemWidth。

columns 斷點鎖定(1/2/3 列)+ 自訂 #load-more 按鈕

加载中...

loadMode auto:觸底自動載入

加载中...

total 剩餘計數 + 自動收斂

加载中...

載入更多(loadMode 三態,預設 button)

loadMode行為場景
'button'(預設)底部按鈕,傳 total 時帶計數「加载更多 (N)」(即「載入更多 (N)」,元件實際輸出為簡體中文):再傳 pageSize 則 N = min(pageSize, 剩餘),否則 N = 剩餘全列表頁
'auto'近觸底 IO 哨兵自動觸發(autoThreshold 提前量;首屏未填滿會持續填充)無限滾動列表
'none'純網格分類首頁多行內容區塊;頁碼翻頁(配 SwPagination,替換式整組換 items)

追加式資料流:收到 @load-more 後往 items 追加;內部 busy 鎖 + loading prop 雙鎖防重複觸發(items 追加 / loading 收尾自動解鎖,失敗場景可重試)。無更多資料時置 finished(傳了 total 時 remaining=0 自動視為到底)。

失敗重試:請求失敗時父層置 error: true,載入區變「加载失败,点击重试」按鈕(點擊照常 emit @load-more,父層重試發請求前清 error);auto 模式失敗時哨兵移除、轉手動重試(防失敗自動循環),error 清掉並追加後自動恢復。

失敗重試:error 置位 → 重試按鈕 → 清錯繼續(含 page-size 按鈕計數)

加载中...

loadMode none:分類首頁內容區塊(純網格)

加载中...

標準用法

<script setup lang="ts">
const items = ref<Movie[]>([])
const total = ref(0)
const loading = ref(false)

async function loadMore() {
  loading.value = true
  try {
    const r = await request<MovieList>('/movie/list', { body: { offset: items.value.length } })
    items.value = [...items.value, ...r.list]
    total.value = +r.total
  } finally {
    loading.value = false
  }
}
await loadMore()
</script>

<template>
  <SwGallery :items="items" :total="total" :loading="loading" :min-item-width="180" @load-more="loadMore">
    <template #default="{ item }">
      <SwLink :to="`/movie/${item.id}`" :track="{ /* 卡片埋點走 SwLink,網格不內建 */ }">
        <SwImage :src="item.img" :alt="item.name" ratio="2/3" />
        <p>{{ item.name }}</p>
      </SwLink>
    </template>
  </SwGallery>
</template>

Props

名稱型別必填預設值說明
itemsT[]✓—追加式資料來源(泛型,元件不關心形狀)
minItemWidthnumber | string240卡片最小寬(auto-fill 模式)。number 視作 px;string 原樣透傳,可傳 min(15.625rem, 46%) / var(--x)
columnsnumber | { mobile?, tablet?, desktop? }undefined鎖定列數,傳了覆蓋 minItemWidth
loadMode'button' | 'auto' | 'none''button'載入更多模式
loadingbooleanfalse外部載入態(雙鎖之一)
finishedbooleanfalse無更多資料
totalnumberundefined總數 → 按鈕計數;remaining=0 視為到底
pageSizenumberundefined每次載入條數 → 按鈕計數顯示 min(pageSize, 剩餘);不傳退回剩餘數
errorbooleanfalse上次載入失敗(父層維護);true 時載入區變「加载失败,点击重试」(元件實際輸出為簡體中文)
autoThresholdnumber | string200auto 哨兵提前量。number 視作 px;string 原樣透傳給 rootMargin,可用 % 按視口比例預取。執行時可改(會重建 IO)
ariaLabelstringundefined傳了才輸出 role="region" + aria-label

Events

名稱攜帶說明
load-more—請父層追加 items(雙鎖內防重複)

Slots

名稱作用域說明
default{ item, index }每張卡片(業務渲染全部視覺)
load-more{ loading, remaining, error }自訂載入更多按鈕區
finished—到底文案(預設「已经到底了」,元件實際輸出為簡體中文)
empty—items 為空的空態(預設「暂无内容」,元件實際輸出為簡體中文)

Expose

名稱說明
loadMore()命令式觸發一次載入(受雙鎖約束)

CSS 變數

變數預設說明
--sw-gallery-gap1rem網格間距
--sw-gallery-min由 minItemWidth 寫入最小卡寬
--sw-gallery-template未設時走 minItemWidth 自適應自訂斷點逃生艙:columns prop 只有 mobile/tablet/desktop 三檔,需要更多斷點時不傳 columns、改在自己的媒體查詢裡設本變數(值即 grid-template-columns)。與 columns 二選一,傳了 prop 會覆蓋它

注意事項

  • 埋點不內建:卡片曝光 / 點擊走卡片內 SwLink :track;網格本身零上報。
  • 翻頁器場景:頁碼翻頁是替換式資料流,用 loadMode="none" + SwPagination 組合(framework#131),不要把頁碼塞進 Gallery。
  • 選型對照(橫滾 / 輪播 / 影片流 / 網格)見 SwRail 選型表。
  • 失敗重試要同時傳 :loading:error / loading 都由父層維護;失敗時只傳 :error 不傳 :loading,內部載入鎖不釋放、重試點擊無效——請同時傳 :loading,並在重試發請求前把 error 清回 false。
  • @load-more 要配 :finished 或 :total:兩者都不傳則永遠判不到「到底」,button 模式按鈕常駐、auto 模式哨兵反覆觸發拉空頁(死循環)。無更多資料時置 :finished="true",或傳 :total 讓剩餘歸零自動收斂。

相關