文章

Astro 内容站:ArticleShell 组件、详情页元信息与章节前后导航

统一文章和系列章节的详情页外壳,让返回链接、摘要、元信息、相关文章与章节导航都在一处收束。

列表页可以共用卡片组件,详情页也有同样的问题。

当前站点至少有两种详情页:

  • 文章详情页
  • 系列章节详情页

两者正文不同,但外层需求很接近:

  • 返回上一级
  • 显示标题和摘要
  • 显示日期、分类或章节编号
  • 在需要时给出相关文章
  • 在系列中提供上一章、下一章

于是当前仓库把这层外壳抽成了 src/components/articles/ArticleShell.astro

ArticleShell 是纯展示层

这个组件不自己查数据,也不自己推导上下章,只接收整理好的输入:

type ArticleLink = {
  href: string;
  label: string;
  meta?: string;
  description?: string;
};

以及这些 props:

  • backLink
  • eyebrow
  • title
  • summary
  • metaItems
  • previousLink
  • nextLink
  • relatedHeading
  • relatedItems

这一步把组件边界定得很准。它只负责“详情页该怎么长”,不负责“这些数据从哪来”。

文章详情页直接吃它

ArticleDetailPageView.astro 里,页面先完成这些工作:

  • render(article) 拿到正文内容
  • getRelatedArticles(...) 找同分类相关文章

然后把已经准备好的数据喂给 ArticleShell

<ArticleShell
  backLink={{ href: getArticlesPath(), label: copy.articles.backToList }}
  eyebrow={copy.articles.heading}
  title={article.data.title}
  summary={article.data.description}
  metaItems={[formatContentDate(article.data.pubDate), article.data.category]}
  relatedHeading={copy.articles.relatedHeading}
  relatedItems={...}
>
  <Content />
</ArticleShell>

这让文章详情页的页面组件只做“数据准备”,而不是在页面里重新写一遍外层结构。

这层头部结构现在又继续向上复用了 PageHero,所以 ArticleShell 自己不再内联写标题区骨架,而是专注在“详情页外壳”这件事上。

系列章节页用的是同一个壳

SeriesChapterPageView.astro 也复用 ArticleShell,只是喂进去的数据不同:

  • backLink 返回系列目录页
  • eyebrow 显示系列标题
  • metaItems 显示章节编号和发布日期
  • previousLink / nextLink 来自 getSeriesChapterContext(...)

也就是说,系列章节页和文章页的差异被压缩到了数据,而不是模板。

章节前后导航因此自然成立

系列页里最重要的外层能力,是上下章导航。当前实现没有把这段导航写死在章节页面里,而是让 ArticleShell 接受两个可选链接:

previousLink={...}
nextLink={...}

当它们存在时,组件自动渲染底部导航区;没有时就不显示。

这个设计很干净,因为:

  • 文章详情页通常不需要前后章
  • 系列章节页天然需要
  • 组件本身不用知道“你现在是不是系列”

元信息也统一成一条流水线

ArticleShell 内部会把 metaItems 过滤并拼成一行:

const metaLine = metaItems.filter(Boolean).join(" · ");

所以不同详情页只要准备好自己的元信息即可:

  • 文章页:日期 + 分类
  • 章节页:章节编号 + 日期

这种小接口看起来简单,但正好把详情页之间重复又略有差异的地方压平了。

为什么要把“相关文章”也放进去

因为相关文章和上下章一样,都是详情页尾部的补充导航。它们不属于正文,也不该散落到页面模板里。放进同一个壳组件之后,详情页的结构就固定成了:

  1. 返回链接
  2. 标题区
  3. 正文区
  4. 上下文导航区
  5. 相关推荐区

这比在不同详情页各自长出一份“尾部结构”更稳定。

当前实现里,相关文章本身也已经切回统一卡片组件:

  • 最多 4 条
  • 桌面双列
  • 移动端单列

所以 ArticleShell 现在既统一了详情页骨架,也统一了详情页尾部的导航语言。

当前做法的收益

现在详情页这条线已经被拆成两层:

  • page view 负责取内容、找翻译、算导航、组数据
  • ArticleShell 负责统一渲染详情页外壳

这样之后,无论你继续扩写文章,还是再加新的系列类型,都不需要重新发明一套详情页模板。

相关文章

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

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

2026-04-16

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

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

2026-04-16

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

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

2026-04-16

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

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

2026-04-16