Astro 主题开发 · 第 2 章:组件与 Props
/ 5 min read
本文对应官方文档Astro 组件,示例在其基础上改编。
学习目标:掌握组件的完整语法与 Props 约定,理解主题组件的接口设计。
组件的解剖
Astro 组件就是一个 .astro 文件,默认只输出 HTML、零 JS。结构分两段:
---// 组件脚本:import、取数、定义变量——只在构建时运行interface Props { title: string tags?: string[]}const { title, tags = [] } = Astro.props---<!-- 组件模板:输出 HTML --><article> <h2>{title}</h2> {tags.length > 0 && <p>{tags.join(' / ')}</p>}</article>两段都是可选的:没有模板的组件可以做纯逻辑封装,没有脚本的组件就是纯静态片段。组件文件里默认不渲染任何东西——忘写 <h2>{title}</h2> 这类模板,页面上就是一块空白,排查“组件不显示”时先看这里。
Props:主题组件的对外接口
Props 接口是 TypeScript 的类型声明,配合 Astro.props 解构使用。它对主题开发有双重意义:
- 文档作用:使用者看你组件的第一件事就是看 Props——这是组件的 API 签名;
- 编辑器补全:使用者在自己的页面里用你的组件时,props 拼错立刻有红线。
设计 Props 时的主题化考量:
- 必填越少越好:能给默认值的都给默认值(
tags = []),使用者只传他关心的; - 传数据不传配置:组件需要的“站点级配置”(如站点标题)不要让使用者层层手动传——从主题配置里读(第 6 章),组件签名保持干净;
- 回调解耦:需要自定义渲染的地方用
slot(下一章)而不是传 JSX 回调——Astro 是构建时框架,没有 React 那种回调渲染。
组合:组件用组件
组件在 frontmatter 里 import,在模板里当标签用,嵌套无限制:
---import PostCard from './PostCard.astro'import Pagination from './Pagination.astro'---<PostCard post={post} /><Pagination page={2} total={10} />没有“注册”环节、没有运行时开销——构建时所有组件直接内联成最终 HTML。这意味着主题组件的拆分粒度可以很自由,按“一个组件一件事”切就行。
经典坑:class 传不进去
给组件传 class 想从外面控制它的样式?直接写 class={className} 解构会编译报错——class 在 JS 里是保留字。官方姿势是解构时重命名:
---const { class: className, ...rest } = Astro.props---<div class={className} {...rest}> <slot /></div>还有一个隐蔽点:组件内 <style> 的作用域样式不会作用于你转手包出去的内容(下一章细讲),所以包装类组件(Card、Container)都该养成接收 class 并转发的习惯——这是“可主题化组件”的基本礼仪,astro-cactus 的所有包装组件都带这一手。
踩坑提示
- Props 只能从父组件传给子组件,不能从子组件“抛”给父组件——需要反向通信时,用 slot(下一章)或事件思路重新设计。
Astro.props是只读的,别在模板里改它。- 忘写
interface Props不报错,但失去全部类型检查——主题组件永远要写。 - 模板里的
{expression}在构建时求值,不要试图在里面写依赖浏览器环境的代码(window之类)。
练习
- 写一个
TagList.astro,接收tags: string[]并渲染标签链接,带默认值处理空数组。 - 给它加上
class转发,从父组件传入自定义类名验证生效。 - 故意传一个类型错误的 prop(如
tags="astro"),观察构建期报错信息。