Astro 建站实战 · 第 3 章:组件、Props 与布局
/ 4 min read
第 3 章 · 组件、Props 与布局
对应文档:Components · Layouts
学习目标
- 会写接收
Props的组件,并理解构建时求值的含义。 - 掌握
<slot />与命名插槽,看懂「布局就是套了<slot />的组件」。 - 能把页面骨架抽成 Layout,让每个页面只剩差异部分。
概念
Astro 组件没有实例、没有状态、没有生命周期——它更像「构建时执行的模板函数」:栅栏代码跑一次,输出一段 HTML。复用靠三件事:Props 传数据、slot 传结构、import 传位置。
动手实践
Props
---interface Props { title: string; href: string; date?: Date;}const { title, href, date } = Astro.props;---<article> <h3><a href={href}>{title}</a></h3> {date && <time datetime={date.toISOString()}>{date.toLocaleDateString("zh-CN")}</time>}</article>interface Props 是纯 TypeScript,编辑器全程检查。Astro 组件不能有 className 这类运行时魔法——写什么就是什么。
slot 与布局
布局 = 套了 <slot /> 的组件。命名插槽用 <slot name="x">,使用方用 slot="x" 属性填充:
---const { title } = Astro.props;---<html lang="zh-CN"> <head><title>{title}</title></head> <body> <nav>…导航…</nav> <main><slot /> {/* 页面内容注入这里 */}</main> <footer>…</footer> </body></html>---import Base from "../layouts/Base.astro";---<Base title="关于"> <h1>关于我</h1> <p>普通内容进默认 slot。</p> <aside slot="sidebar">命名插槽按位置注入。</aside></Base>布局套布局
布局也是组件,自然可以嵌套:页面级 Layout 引入更外层的文档骨架,逐层组合。
踩坑提示
- 给「整页布局」传进来的
<slot />内容是在使用方上下文求值的——样式作用域属于各页面自己,布局里的 scoped 样式管不到页面内容(需要时用:global()或全局样式,第 4 章)。 Astro.props解构后别忘了默认值写法:const { draft = false } = Astro.props。- slot 不是 props:传结构用 slot,传数据用 props,别混。
对照本站
- src/layouts/Base.astro:全站的文档骨架(
<html>、<head>、页头页脚),Props里除了meta还有一个布尔seriesRail——这正是上一轮「系列页三栏布局」改造的入口:布局通过 prop 感知页面类型,给<body>附加series-rail-layout类。 - src/layouts/BlogPost.astro:布局套布局的示范——文章布局在 BaseLayout 之上再叠一层「页头 + 正文 + 目录侧栏」的结构,并把
<slot />(正文 Markdown)放进 prose 容器。 - src/components/layout/Header.astro:读
site.config.ts的menuLinks数组渲染导航——组件 + 配置驱动的典型写法,改导航菜单不用碰组件。
练习
- 把第 2 章的名言页公共骨架抽成
QuoteLayout.astro。 - 给布局加一个命名插槽
header-extra,在其中一个页面里塞一个搜索框占位。 - 给
PostCard加pinned布尔 prop,置顶时多渲染一个 📌。
遗留问题
组件和布局的问题解决了,但所有页面还共用同一套样式,改一个颜色要全局搜索替换。样式体系怎么组织?下一章。