文章

Astro 内容站:ContentCardList 组件与首页、系列页组合

用统一的卡片组件承接首页摘要和系列目录,让需要快速浏览的区块共享稳定的信息结构。

当前站点已经不是只有一个文章列表页了。现在至少有这几种“列表型页面”:

  • 首页的最新文章
  • 首页的最新系列章节
  • 系列列表页

这些页面的数据来源不同,但有一部分都属于“浏览几个最新条目或目录项”。当前仓库的做法,是先把共同的卡片 UI 抽成 ContentCardList.astro,再让 page view 组件只负责喂数据。首页和系列总览现在都继续走卡片流;文章页和归档页则因为要强调日期、分类与分页,独立成了更高密度的索引列表组件。

卡片组件只认统一输入

ContentCardList 的输入很小:

export type ContentCardItem = {
  href: string;
  eyebrow?: string;
  title: string;
  description?: string;
  meta?: string;
};

再加两个控制项:

  • emptyLabel
  • layout?: "stack" | "grid"

这意味着无论卡片来自首页摘要还是系列目录项,只要先被映射成这几个字段,就能被同一个组件渲染。

组件层只管渲染,不管来源

ContentCardList.astro 本身不知道文章来自哪里,也不知道系列有什么区别。它只做这些事:

  • 有内容时渲染卡片列表
  • 没有内容时显示空状态文本
  • 根据 layout 决定是纵向堆叠还是响应式网格

核心结构如下:

{items.length > 0 ? (
  <div class:list={["content-card-list", layout === "grid" && "content-card-list-grid"]}>
    {items.map((item) => (
      <a class="content-card" href={item.href}>
        <div class="content-card-body">
          {item.eyebrow ? <p class="content-card-eyebrow">{item.eyebrow}</p> : null}
          <h2>{item.title}</h2>
          {item.description ? <p class="content-card-description">{item.description}</p> : null}
          {item.meta ? <p class="content-card-meta">{item.meta}</p> : null}
        </div>
      </a>
    ))}
  </div>
) : (
  <p>{emptyLabel}</p>
)}

这里的设计重点,是把“信息结构”稳定下来,而不是在组件里判断一堆内容类型。

首页用两组数据,复用一套卡片

HomePageView.astro 现在同时组合两块数据:

  • getPublishedArticles().slice(0, 4)
  • getLatestSeriesChapters(4)

但最终都被整理成卡片项交给 ContentCardList。而 section 标题本身则交给 PageSectionHeader,因此首页只是把两个 feed 摆进稳定的区块骨架里,并不需要为“最新文章”和“最新章节”各写一套列表组件。

系列目录仍然适合卡片流

后来文章页和归档页都改成了更高密度的索引列表,但系列目录和首页摘要仍然更适合卡片流,因为它们更像“浏览入口”而不是“时间归档”。

SeriesPageView.astro 现在也重新回到 ContentCardList,与首页摘要共用同一套浏览入口卡片语言。

这也说明了一件事:组件复用并不意味着所有列表都必须长得一样,关键是让“浏览入口”和“归档索引”各自用对信息密度。

归档页后来单独拆出

一开始归档页也能复用卡片组件,因为它同样只是“把数据映射成统一字段再渲染”。但当归档页需要强调这些信息时:

  • 年份分组
  • 明确的发布日期
  • 文章分类
  • 系列章节所属系列

卡片流就开始显得不够紧凑。于是归档页后来改成了专用的时间序列组件,保留统一页面壳层,但不再强行复用 ContentCardList

这个变化也说明了一件事:统一组件很有用,但当页面任务从“浏览最近内容”转成“按时间查找全部内容”时,视觉密度和信息结构也应该跟着变化。

Page view 组件因此保持很薄

当前和卡片直接相关的 src/components/pages/ 文件主要是:

  • HomePageView.astro
  • SeriesPageView.astro

本质上都在做同一件事:

  • 读取数据
  • 选用页面文案
  • 把数据映射成卡片项
  • 交给通用组件渲染

这也是为什么路由文件现在能薄到只剩一句:

<SeriesPageView locale="zh" />

这种拆法的好处

当前结构把变化点分得很清楚:

  • 如果改视觉,就改 ContentCardList
  • 如果改归档时间线,就改归档专用组件
  • 如果改数据排序或来源,就改 lib/*
  • 如果改页面组合,就改 page view

这样首页和系列页虽然都在展示“内容卡片”,但不会因为共用一个组件而互相缠死;而文章页和归档页也能在需要更高密度时独立演化。

相关文章

Astro 内容站:PageHero 组件与页面头部统一

把列表页、首页、系列页和详情页里重复的标题区抽成 PageHero,让返回链接、eyebrow、标题和状态文案共用一套骨架。

2026-04-16

Astro 内容站:PageSectionHeader 组件与区块标题复用

把 section 标题、补充说明、右侧动作和分组计数统一到一个组件里,让首页、归档和索引列表共享稳定的区块头结构。

2026-04-16

Astro 内容站:组件组合重构、重复代码清理与文档同步

一次收口页面骨架、分页辅助、概览卡和旧文档漂移,把页面组合整理成更稳定的单组件文件结构。

2026-04-16

Astro 内容站:SummaryStatGrid 组件与归档总览卡

把归档页里重复的统计卡结构抽成 SummaryStatGrid,为总条目、文章数、章节数和最近更新时间提供统一的数值卡组件。

2026-04-16