- 起步
- 核心概念
- 教程
- 基础内容
- 内置功能
- 集成
- 操作指南
- 使用指南
- 配置
- 参考
- 社区资源
- 其他
- 为文档做出贡献
- 手动安装 Astro
- 升级到 Astro v4
- 升级到 Astro v3
- 升级到 Astro v2
- Legacy v0.x Upgrade Guide
- 从 Create React App(CRA)迁移
- 关于本教程
- 第一单元:前期准备
- 准备开发环境
- 创建你的第一个 Astro 项目
- 你的第一行 Astro 代码
- 创建在线代码仓库
- 将你的网站部署到网络
- 第二单元:页面
- 创建你的第一个 Astro 页面
- 编写你的第一篇 Markdown 博客文章
- 添加「关于你」的动态内容
- 给你的「关于」页面添加样式
- 应用全局样式
- 第三单元:组件
- 创建一个可重复使用的导航组件
- 创建社交媒体 footer
- 自己动手搭建导航 Header
- 编写你的第一个浏览器脚本
- 第四单元:布局
- 编写你的第一个布局
- 创建并传递数据到博客布局
- 布局结合,两全其美
- 第五单元 - Astro API
- 创建文章存档页
- 生成标签页面
- 编写标签索引页面
- 添加 RSS 订阅源
- 第六单元 - Astro 群岛
- 搭建你的第一个 Astro 岛屿
- 回到干燥的陆地。让你的博客从白天到黑夜,无需岛屿!
- 恭喜你!
- @astrojs/mdx
- 添加阅读时间
- 创建开发者工具栏应用
- @astrojs/alpinejs
- @astrojs/lit
- @astrojs/preact
- @astrojs/react
- @astrojs/solid-js
- @astrojs/svelte
- @astrojs/vue
- @astrojs/cloudflare
- @astrojs/netlify
- @astrojs/node
- @astrojs/vercel
- @astrojs/db
- @astrojs/markdoc
- @astrojs/partytown
- @astrojs/sitemap
- @astrojs/tailwind
- 使用流式处理来提升页面性能
- 从 Gatsby 迁移
- 从 Next.js 迁移
- 从 NuxtJS 迁移
- 从 Docusaurus 迁移到 Astro
- 从 Eleventy 迁移到 Astro
- 从 GitBook 迁移到 Astro
- 从Gridsome迁移到Astro
- 从 Hugo 迁移
- 从 Jekyll 迁移
- 从 Pelican 迁移
- 从 SvelteKit 迁移
- 从VuePress迁移
- 从 WordPress 迁移
- 状态共享
- Storyblok 与 Astro
- Contentful 与 Astro
- ButterCMS & Astro
- Builder.io & Astro
- Cosmic 与 Astro
- DatoCMS 与 Astro
- Front Matter CMS 与 Astro
- Ghost & Astro
- Hashnode & Astro
- Hygraph 与 Astro
- Keystatic & Astro
- Kontent.ai 与 Astro
- 无头模式的 Statamic 与 Astro
- Strapi 与 Astro
- Tina CMS 与 Astro
- Umbraco & Astro
- 无头(headless)模式的 WordPress 与 Astro
- ApostropheCMS 与 Astro
- Caisy & Astro
- CloudCannon与Astro
- Crystallize 与 Astro
- Decap CMS 与 Astro
- Directus 与 Astro
- KeystoneJS 与 Astro
- microCMS & Astro
- Payload CMS 与 Astro
- Prepr CMS & Astro
- Prismic & Astro
- Sanity & Astro
- Sitecore 体验管理器 & Astro
- Spinal & Astro
- 创作内容
- Firebase 与 Astro
- Supabase 与 Astro
- Turso 和 Astro
- Xata 与 Astro
- Appwrite & Astro
- 部署你的 Astro 站点至 Netlify
- 部署你的 Astro 站点至 Vercel
- 如何将你的 Astro 网站部署到 Deno
- 部署你的 Astro 站点至 GitHub Pages
- 部署你的 Astro 站点至 GitLab Pages
- 部署你的 Astro 站点至 Cloudflare Pages
- 将你的 Astro 网站部署到 AWS
- 将你的 Astro 网站通过 Flightcontrol 部署到 AWS
- 将你的 Astro 网站通过 SST 部署到 AWS
- 将你的 Astro 网站部署至 Google Cloud
- 部署你的 Astro 站点至 Google Firebase 托管
- 将你的 Astro 网站部署到 Heroku
- 将你的 Astro 网站部署到 Microsoft Azure
- 部署你的 Astro 站点至 Buddy
- 将你的 Astro 网站部署到 Edgio
- 将你的 Astro 站点部署到 Fly.io
- 将你的 Astro 网站部署到 Render
- 将你的 Astro 网站部署到 Stormkit
- 将你的 Astro 网站部署到 Surge
- 通过 Cleavr 部署你的 Astro 网站
- 将你的 Astro 站点部署到 Kinsta 应用托管
- 将你的 Astro 网站部署到 Space
- 将你的 Astro 站点部署到 Zeabur
- 将你的 Astro 网站部署到 Zerops
- 添加 RSS 摘要
- 安装一个 Vite 或 Rollup 插件
- 构建自定义图像组件
- 使用 API 路由构建表单
- 在 Astro 页面中构建 HTML 表单
- 在 Astro 中使用 Bun
- 调用服务器端点
- 校验验证码
- 用 Docker 来构建你的 Astro 网站
- 动态导入图片
- 为链接添加图标
- 添加 i18n 功能
- 添加最后修改时间
- 在 Astro 组件中共享状态
- 使用 Tailwind Typography 美化渲染后的 Markdown
- Unknown compiler error.
- Astro.redirect is not available in static mode.
- Astro.clientAddress is not available in current adapter.
- Astro.clientAddress cannot be used inside prerendered routes.
- Astro.clientAddress is not available in static mode.
- No static path found for requested path.
- Invalid type returned by Astro page.
- Missing value for client:media directive.
- No matching renderer found.
- No client entrypoint specified in renderer.
- Missing hint on client:only directive.
- Invalid value returned by a getStaticPaths path.
- Invalid entry inside getStaticPath's return value
- Invalid value returned by getStaticPaths.
- getStaticPaths RSS helper is not available anymore.
- Missing params property on getStaticPaths route.
- Invalid value for getStaticPaths route parameter.
- getStaticPaths() function required for dynamic routes.
- Invalid slot name.
- Cannot use Server-side Rendering without an adapter.
- No import found for component.
- Invalid prerender export.
- Invalid component arguments.
- Page number param not found.
- Image missing required "alt" property.
- Error while loading image service.
- Missing image dimensions
- Failed to retrieve remote image dimensions
- Unsupported image format
- Unsupported image conversion
- Prerendered dynamic endpoint has path collision.
- Expected src to be an image.
- Expected image options.
- Cannot set both densities and widths
- Image not found.
- Could not process image metadata.
- Image not found.
- Could not transform image.
- Unable to set response.
- The middleware didn't return a Response.
- The middleware returned something that is not a Response object.
- The endpoint did not return a Response.
- Value assigned to locals is not accepted.
- Astro.response.headers must not be reassigned.
- Can't load the middleware.
- Local images must be imported.
- Astro.glob() used outside of an Astro file.
- Astro.glob() did not match any files.
- A redirect must be given a location with the Location header.
- Invalid dynamic route.
- Could not find Sharp.
- Unknown Vite Error.
- Could not import file.
- Invalid glob pattern.
- Astro couldn't find the correct page to render
- The provided locale does not exist.
- Index page not found.
- You can't use the current function with the current strategy
- Prerendered routes aren't supported when internationalization domains are enabled.
- 启用了手动国际化路由但没有提供中间件。
- Astro can't render the route.
- Unhandled rejection
- i18n Not Enabled
- Route not found.
- Unknown CSS Error
- CSS Syntax Error
- Unknown Markdown Error.
- Failed to parse Markdown frontmatter.
- Invalid frontmatter injection.
- MDX integration missing.
- Unknown configuration error.
- Specified configuration file not found.
- Legacy configuration detected.
- Unknown CLI Error.
- Failed to generate content types.
- Unknown Content Collection Error.
- Content entry frontmatter does not match schema.
- Invalid content entry slug.
- Content Schema should not contain slug.
- Collection does not exist
- Content and data cannot be in same collection.
- Collection contains entries of a different type.
- Data collection entry failed to parse.
- Duplicate content entry slug.
- Actions must be used with server output.
- Unsupported transform in content config.
组件
Astro 组件是 Astro 项目的基础构建模块。它们是纯 HTML、无需客户端运行时的模板组件。你可以通过文件扩展名 .astro
来识别 Astro 组件。
Astro 组件非常灵活的。通常情况下,Astro 组件会包含一些可在页面中复用的 UI,如 header 或简介。在其他时候,Astro 组件可能包含一个较小的 HTML 片段,像是常见的使 SEO 更好的 <meta>
标签集合。Astro 组件甚至可以包含整个页面布局。
Astro 组件最重要的一点是它们不会在客户端上渲染。它们在构建时或使用 服务器端渲染(SSR) 按需呈现为 HTML。你可以在组件 frontmatter 中编写 JavaScript 代码,所有这些代码都将从发送到用户浏览器的最终页面中删除。结果是一个更快的网站,默认情况下不用任何 JavaScript。
当你的 Astro 组件确实需要客户端交互性时,你可以添加 标准 HTML <script>
标签 或 UI 框架组件。
组件概述
Astro 组件是由两个主要部分所组成的——组件 script 和组件模板。每个部分分工处理最终呈现出一个既容易使用,又有足够的表现力来实现你的想象的框架。
src/components/EmptyComponent.astro---
// 组件脚本(JavaScript)
---
<!-- 组件模板(HTML + JS 表达式)-->
组件脚本
Astro 使用代码围栏(---
)来识别 Astro 组件中的组件脚本。如果你以前写过 Markdown,你可能已经熟悉了叫做 frontmatter 的类似概念。Astro 的组件脚本的想法直接受到了这个概念的启发。
你可以使用组件脚本来编写渲染模板所需 JavaScript 代码。这可以包括:
- 导入其他 Astro 组件
- 导入其他框架组件,如 React
- 导入数据,如 JSON 文件
- 从 API 或数据库中获取内容
- 创建你要在模板中引用的变量
---
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeReactComponent.jsx';
import someData from '../data/pokemon.json';
// 访问传入的组件参数,如 `<X title="Hello, World"/>`
const { title } = Astro.props;
// 获取外部数据,甚至可以从私有 API 和数据库中获取
const data = await fetch ('SOME_SECRET_API_URL/users').then (r => r.json ());
---
<!-- 你的模板在这! -->
代码围栏的设计是为了保证你在其中编写的 JavaScript 被“围起来”。它不会逃到你的前端应用程序中,或落入你的用户手中。你可以安全地在这里写一些昂贵或敏感的代码(比如调用你的私人数据库),而不用担心它会出现在你的用户的浏览器中。
组件模板
在组件脚本下面的是组件模板。组件模板决定了你的组件的 HTML 输出。
如果你在这里写普通的 HTML,你的组件将在任何 Astro 页面上呈现它被导入和使用的 HTML。
但是,Astro 的组件模板语法 还支持 JavaScript 表达式、Astro <style>
和 <script>
标签、导入的组件和特殊的 Astro 指令。组件脚本中定义的数据和值可以在组件模板中使用,以生成动态创建的 HTML。
---
// 你的组件脚本在这!
import Banner from '../components/Banner.astro';
import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
const myFavoritePokemon = [/* ... */];
const { title } = Astro.props;
---
<!-- 支持 HTML 注释! -->
{/* JS注释语法也是有效的! */}
<Banner />
<h1>你好,世界!</h1>
<!-- 使用组件脚本中的 props 和其他变量: -->
<p>{title}</p>
<!-- 包括其他带有 `client:` 指令的激活组件: -->
<ReactPokemonComponent client:visible />
<!-- 混合 HTML 和 JavaScript 表达式,类似于 JSX: -->
<ul>
{myFavoritePokemon.map ((data) => <li>{data.name}</li>)}
</ul>
<!-- 使用模板指令从多个字符串甚至对象来构建类名! -->
<p class:list={["add", "dynamic", {classNames: true}]} />
基于组件的设计
组件的设计是为了 可复用 和 可组合。你可以在组件中使用其他组件来构建越来越高级的 UI。例如,Button
组件可用于创建 ButtonGroup
组件:
---
import Button from './Button.astro';
---
<div>
<Button title="按钮 1" />
<Button title="按钮 2" />
<Button title="按钮 3" />
</div>
组件参数
Astro 组件可以定义和接受参数。然后,这些参数可用于组件模板以呈现 HTML。可以在 frontmatter script 中的 Astro.props
中使用。
这是一个接收 greeting
和 name
参数的组件示例。请注意,要接收的参数是从全局 Astro.props
对象中解构的。
---
// 使用:<GreetingHeadline greeting="你好" name="朋友" />
const { greeting, name } = Astro.props
---
<h2>{greeting},{name}!</h2>
当该组件在其他 Astro 组件、布局或页面中导入并渲染时,可以将这些 props 作为属性传递:
src/components/GreetingCard.astro---
import GreetingHeadline from './GreetingHeadline.astro';
const name = "Astro";
---
<h1>Greeting Card</h1>
<GreetingHeadline greeting="嗨" name={name} />
<p>希望你有美好的一天!</p>
你也可以使用 TypeScript 中的 interface 来定义 Props
类型。Astro 会自动在你的 frontmatter 中找到 Props
interface,并为你的项目提供类型警告/错误。这些 props 也可以在从 Astro.props
解构时给出默认值。
---interface Props { name: string; greeting?: string;}
const { greeting = "你好", name } = Astro.props;
---
<h2>{greeting},{name}!</h2>
当没有提供组件参数时,可以给它默认值来使用。
src/components/GreetingHeadline.astro---
const { greeting = "你好", name = "宇航员" } = Astro.props;
---
<h2>{greeting},{name}!</h2>
插槽
<slot />
元素是嵌入外部 HTML 内容的占位符,你可以将其他文件中的子元素注入(或“嵌入”)到组件模板中。
默认情况下,传递给组件的所有子元素都将呈现在 <slot />
中。
---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';
const { title } = Astro.props;
---
<div id="content-wrapper">
<Header />
<Logo />
<h1>{title}</h1>
<slot /> <!-- 子项会在这 -->
<Footer />
</div>
src/pages/fred.astro---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Fred 的页面"> <h2>关于 Fred 的一切</h2> <p>这里有一些关于 Fred 的东西。</p>
</Wrapper>
这种模式是 Astro 布局组件 的基础:整个 HTML 内容的页面可以用 <SomeLayoutComponent></SomeLayoutComponent>
标签围起来并发送到组件,以在那里定义的公共页面元素中呈现。
命名插槽
Astro 组件也可以有命名插槽。这允许你仅将具有相应插槽名称的 HTML 元素传递到插槽的位置。
src/components/Wrapper.astro---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';
const { title } = Astro.props;
---
<div id="content-wrapper">
<Header />
<slot name="after-header" /> <!-- 带有 `slot="after-header"` 属性的子项在这 -->
<Logo />
<h1>{title}</h1>
<slot /> <!-- 没有 `slot` 或有 `slot="default"` 属性的子项在这 -->
<Footer />
<slot name="after-footer" /> <!-- 带有 `slot="after-footer"` 属性的子项在这 -->
</div>
要将 HTML 内容注入特定插槽,可以在任何子元素上使用 slot
属性来指定插槽的名称。组件的所有其他子元素将被注入到 default
(未命名)的 <slot />
中。
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="弗雷德的页面">
<img src="https://www.wenjiangs.com/wp-content/uploads/2024/astro/my.photo" slot="after-header" />
<h2>关于弗雷德的一切</h2>
<p>这里有一些关于弗雷德的资料。</p>
<p slot="after-footer">版权所有 2022</p>
</Wrapper>
要将多个 HTML 元素传递到组件的 <slot/>
占位符中而无需包装 <div>
,可以在 Astro 的 <Fragment/>
组件上使用 slot=""
属性:
---
// 创建一个自定义的表格,为头部和主体内容设置具名的 slot 占位符
---
<table class="bg-white">
<thead class="sticky top-0 bg-white"><slot name="header" /></thead>
<tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="body" /></tbody>
</table>
使用 slot=""
属性以指定 "header"
和 "body"
内容以注入多行和多列的 HTML 内容。也可以对单个 HTML 元素进行样式设置:
---
import CustomTable from './CustomTable.astro';
---
<CustomTable> <Fragment slot="header"> <!-- 传递表头 --> <tr><th>产品名称</th><th>库存单位</th></tr> </Fragment>
<Fragment slot="body"> <!-- 传递表格主体 --> <tr><td>人字拖</td><td>64</td></tr> <tr><td>靴子</td><td>32</td></tr> <tr><td>运动鞋</td><td class="text-red-500">0</td></tr> </Fragment></CustomTable>
请注意,命名插槽必须是组件的直接子级。不能通过嵌套元素传递命名插槽。
插槽回退内容
插槽还可以渲染回退内容。当没有匹配的子元素传递给插槽时,<slot />
元素将呈现其自己的占位符子元素。
---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';
const { title } = Astro.props;
---
<div id="content-wrapper">
<Header />
<Logo />
<h1>{title}</h1>
<slot> <p>当没有子项传入插槽时使用此回退</p>
</slot>
<Footer />
</div>
传递插槽
插槽可以传递给其他组件。例如,在创建嵌套布局时:
src/layouts/BaseLayout.astro---
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} /> <slot name="head" />
</head>
<body> <slot />
</body>
</html>
src/layouts/HomeLayout.astro---
import BaseLayout from "./BaseLayout.astro";
---
<BaseLayout> <slot name="head" slot="head" /> <slot />
</BaseLayout>
现在,传递给 HomeLayout
的默认插槽和 head
插槽也将会传递给父级的 BaseLayout
组件。
---
import HomeLayout from "../layouts/HomeLayout.astro";
---
<HomeLayout>
<title slot="head">Astro</title>
<h1>Astro</h1>
</HomeLayout>
HTML 组件
Astro 支持导入和使用 .html
文件作为组件,或者将这些文件放在 src/pages
子目录下作为页面。如果你正在复用一个没有使用框架的现有网站代码,或者你想确保你的组件没有动态功能,你可能会需要使用 HTML 组件。
HTML 组件必须只包含有效的 HTML,因此缺乏关键的 Astro 组件功能:
- 它们不支持 frontmatter、服务器端导入或动态表达式。
- 任何
<script>
标签都不会被打包,被视为具有is:inline
。 - 它们只能 引用
public/
文件夹中的资源。
下一步
阅读更多关于如何在 Astro 项目中使用 UI 框架组件 的内容。如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论