API 参考
Astro
Section titled AstroAstro
在所有 .astro
文件中均可用。它有以下功能:
Astro.glob()
Section titled Astro.glob()Astro.glob()
可以在静态网站 setup 中加载本地文件:
---
const posts = await Astro.glob('../pages/post/*.md'); // 返回 ./src/pages/post/*.md 的数组
---
<div>
{posts.slice(0, 3).map((post) => (
<article>
<h1>{post.frontmatter.title}</h1>
<p>{post.frontmatter.description}</p>
<a href={post.frontmatter.url}>Read more</a>
</article>
))}
</div>
.glob()
只需要一个参数:你想导入的本地文件全局相对链接。它异步返回匹配文件的数组。
.glob()
不能接受插值的变量或字符串,因为它们不是静态可分析的。(参见故障排查以了解解决方法)。 这是因为 Astro.glob()
是 Vite 的 import.meta.glob()
的包装器。
Markdown 文件
Section titled Markdown 文件Markdown 文件有以下接口:
export interface MarkdownInstance<T extends Record<string, any>> {
/* 在此文件的 YAML frontmatter 中指定的任何数据 */
frontmatter: T;
/* 该文件的文件路径 */
file: string;
/* 该文件的渲染路径 */
url: string | undefined;
/* 渲染此文件内容的 Astro 组件 */
Content: AstroComponent;
/* 返回该文件中 h1...h6 元素数组的函数 */
getHeadings(): Promise<{ depth: number; slug: string; text: string }[]>;
}
你可以选择使用 TypeScript 泛型指定 frontmatter
变量类型:
---
interface Frontmatter {
title: string;
description?: string;
}
const posts = await Astro.glob<Frontmatter>('../pages/post/*.md');
---
<ul>
{posts.map(post => <li>{post.frontmatter.title}</li>)}
</ul>
Astro.props
Section titled Astro.propsAstro.props
是一个包含任何作为组件属性传递的值的对象。.md
和 .mdx
文件的布局组件接收作为参数的 frontmatter 值。
---
const { title, date } = Astro.props;
---
<div>
<h1>{title}</h1>
<p>{date}</p>
</div>
---
import Heading from '../components/Heading.astro';
---
<Heading title="我的第一篇文章" date="09 Aug 2022" />
📚 进一步了解 Markdown 和 MDX 布局如何处理道具。
📚 了解如何为你的道具添加 Typescript 类型定义。
Astro 文件
Section titled Astro 文件Astro 文件有以下接口:
export interface AstroInstance {
default: AstroComponent;
}
其他文件可能有各种不同的接口,但 Astro.glob()
均接受 TypeScript 泛型,如果你明确知道未被识别的文件类型包含些什么:
---
interface CustomDataFile {
default: Record<string, any>;
}
const data = await Astro.glob<CustomDataFile>('../data/**/*.js');
---
Astro.request
Section titled Astro.requestAstro.request
是标准的 Request 对象。它可以用来获取请求的 url
、headers
、method
,甚至是 body
。可以使用 new URL(Astro.request.url)
来获得链接对象。
<p>Received a {Astro.request.method} request to "{Astro.request.url}".</p>
<p>Received request headers: <code>{JSON.stringify(Object.fromEntries(Astro.request.headers))}</code>
参见:Astro.url
Astro.response
Section titled Astro.responseAstro.response
是标准的 ResponseInit对象。它用于设置页面响应中的 status
、statusText
和 headers
---
if(condition) {
Astro.response.status = 404;
Astro.response.statusText = 'Not found';
}
---
或者设置 header:
---
Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;');
---
Astro.canonicalURL
Section titled Astro.canonicalURL当前页面的标准链接。
Astro.url
Section titled Astro.urlURL对象,由当前 Astro.request.url
的链接字符串值构成。对于与请求的链接的个别属性进行交互是有用的,如路径名和起源。
相当于做 new URL(Astro.request.url)
。
<h1>当前链接是:{Astro.url}</h1>
<h1>当前链接路径名是:{Astro.url.pathname}</h1>
<h1>当前链接源是:{Astro.url.origin}</h1>
你也可以使用 Astro.url
来创建新的链接,并把它作为参数传给 new URL()
。
---
// 示例:使用你的生产域名构建一个规范的URL
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
// 示例:使用你目前的域名构建一个用于SEO元标签的URL
const socialImageURL = new URL('/images/preview.png', Astro.url);
---
<link rel="canonical" href={canonicalURL} />
<meta property="og:image" content={socialImageURL} />
Astro.clientAddress
Section titled Astro.clientAddress指定请求的 IP 地址。这个属性只在为 SSR(服务器端渲染)构建时可用,不应该用于静态网站。
---
const ip = Astro.clientAddress;
---
<div>你的 IP 地址是:<span class="address">{ ip }</span></div>
Astro.site
Section titled Astro.siteAstro.site
返回根据 Astro 配置中的 site
生成的 URL
。如果没指定,将返回根据 localhost
生成的链接。
Astro.generator
Section titled Astro.generatorAstro.generator
是个便捷方法,它可以添加与你当前 Astro 版本一致的 <meta name="generator">
标签。它遵循的格式是 "Astro v1.x.x"
。
<html>
<head>
<meta name="generator" content={Astro.generator} />
</head>
<body>
<footer>
<p>由 <a href="https://astro.build">{Astro.generator}</a> 构建</p>
</footer>
</body>
</html>
Astro.slots
Section titled Astro.slotsAstro.slots
包含修改 Astro 组件插槽的实用函数。
名称 | 类型 | 描述 |
---|---|---|
has |
(name: string) => boolean |
此插槽是否存在内容 |
render |
(name: string, args?: any[]) => Promise<string> |
异步渲染该插槽并返回 HTML |
---
let html: string = '';
if (Astro.slots.has('default')) {
html = await Astro.slots.render('default')
}
---
<Fragment set:html={html} />
Astro.self
Section titled Astro.selfAstro.self
允许 Astro 组件被递归调用。这使得你可以通过在组件模板中使用 <Astro.self>
从自身内部渲染 Astro 组件。这对迭代大型数据存储和嵌套数据结构很有帮助。
---
const { items } = Astro.props;
---
<ul class="nested-list">
{items.map((item) => (
<li>
<!-- 如果有嵌套的数据结构,将渲染 `<Astro.self>` -->
<!-- 并可以通过递归调用来传递参数 -->
{Array.isArray(item) ? (
<Astro.self items={item} />
) : (
item
)}
</li>
))}
</ul>
然后,这个组件可以这样用:
---
import NestedList from './NestedList.astro';
---
<NestedList items={['A', ['B', 'C'], 'D']} />
并渲染这样的 HTML:
<ul class="nested-list">
<li>A</li>
<li>
<ul class="nested-list">
<li>B</li>
<li>C</li>
</ul>
</li>
<li>D</li>
</ul>
getStaticPaths()
Section titled getStaticPaths()如果页面在文件名中使用动态参数,该组件将需要导出一个 getStaticPaths()
函数。
必须要有该函数,因为 Astro 是静态站点生成器。这意味着整个网站是预构建的。如果 Astro 不知道在构建时生成什么页面,你的用户在访问你的网站时就看不到它。
---
export async function getStaticPaths() {
return [
{ params: { /* 必需 */ }, props: { /* 可选 */ } },
{ params: { ... } },
{ params: { ... } },
// ...
];
}
---
<!-- 你的 HTML 模板在这里 -->
getStaticPaths()
函数应该返回对象数组,以确定哪些路径会被 Astro 预渲染。
params
Section titled params每个返回对象的 params
键都会告诉 Astro 要建立什么路径。返回参数必须映射到你的组件文件路径中定义的动态参数和其余参数。
params
被编码到链接中,所以只能由字符串和数字。每个 params
对象的值必须与页面名称中使用的参数一致。
比如说有 src/pages/posts/[id].astro
页面。如果你从这个页面导出 getStaticPaths
并返回以下的路由:
---
export async function getStaticPaths() {
return [
{ params: { id: '1' } },
{ params: { id: '2' } },
{ params: { id: 3 } } // 也可以是数字!
];
}
const { id } = Astro.params;
---
<h1>{id}</h1>
然后 Astro 会在构建时静态地生成 posts/1
、posts/2
和 posts/3
。
通过 props
传递数据
Section titled 通过 props 传递数据为了给每个生成的页面传递额外的数据,你也可以在每个返回的路径对象上设置 props
值。与 params
不同的是,props
没有被编码到链接中,所以并不局限于字符串。
例如,假设你根据从远程 API 获取的数据来生成页面。你可以将完整的数据对象传递给 getStaticPaths
中的页面组件。
---
export async function getStaticPaths() {
const data = await fetch('...').then(response => response.json());
return data.map((post) => {
return {
params: { id: post.id },
props: { post },
};
});
}
const { id } = Astro.params;
const { post } = Astro.props;
---
<h1>{id}: {post.name}</h1>
你也可以传递普通数组,这在生成或缓存已知路径列表时可能会有帮助。
---
export async function getStaticPaths() {
const posts = [
{id: '1', category: "astro", title: "API Reference"},
{id: '2', category: "react", title: "Creating a React Counter!"}
];
return posts.map((post) => {
return {
params: { id: post.id },
props: { post }
};
});
}
const {id} = Astro.params;
const {post} = Astro.props;
---
<body>
<h1>{id}: {post.title}</h1>
<h2>Category: {post.category}</h2>
</body>
然后 Astro 将在构建时使用 pages/posts/[id].astro
中的页面组件静态地生成 posts/1
和 posts/2
。页面可以使用 Astro.props
引用这些数据。
paginate()
Section titled paginate()分页是 Astro 通过 paginate()
函数原生支持网站的常见用例。paginate()
将自动生成数组,从getStaticPaths()
返回,为分页集合的每个页面创建一个URL。页面编号将作为参数传递,而页面数据将作为page
道具传递。
export async function getStaticPaths({ paginate }) {
// 用 fetch()、Astro.glob() 等加载你的数据
const response = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=150`);
const result = await response.json();
const allPokemon = result.results;
// 返回包含分页的所有帖子的路由集合
return paginate(allPokemon, { pageSize: 10 });
}
// 如果设置正确,现在页面已经具备了渲染单页所需的一切参数(见下一节)。
const { page } = Astro.props;
paginate()
:假定文件名为 [page].astro
或 [...page].astro
。page
参数将是链接中的页数。
/posts/[page].astro
:会产生/posts/1
、/posts/2
、/posts/3
等链接。/posts/[...page].astro
:将产生/posts
、/posts/2
/posts/3
等链接。
page
分页参数
Section titled page 分页参数分页会给每个渲染的页面传递 page
参数,代表分页集合中的单页数据。这包括你分页的数据(page.data
)以及该页的元数据(page.url
、page.start
、page.end
、page.total
等)。这些元数据对诸如“下一页”按钮或“显示 100 个中前十个”的信息很有用。
名称 | 类型 | 描述 |
---|---|---|
page.data |
Array |
从 data() 中返回当前页面数据数组 |
page.start |
number |
当前页第一个项目的索引,从 0 开始(例如,如果 pageSize: 25 ,第一页该值未 0 ,第二页为25 ,以此类推)。 |
page.end |
number |
当前页面最后一个项目的索引 |
page.size |
number |
每个页面有多少项目 |
page.total |
number |
所有项目的总数量 |
page.currentPage |
number |
当前页码,从 1 开始 |
page.lastPage |
number |
总页数 |
page.url.current |
string |
获取当前页面的链接(对规范链接很有用)。 |
page.url.prev |
string | undefined |
获取上一页链接(如果在首页,将是undefined )。 |
page.url.next |
string | undefined |
获取下一页链接(如果没有更多的页面,将是undefined ) |
import.meta
Section titled import.meta所有 ESM 模块都包含 import.meta
属性。Astro 基于 Vite 增加了 import.meta.env
。
import.meta.env.SSR
可以用来了解服务器上渲染时长。有时你可能想要不同的逻辑,例如,某个组件应该只在客户端渲染:
import { h } from 'preact';
export default function () {
return import.meta.env.SSR ? <div class="spinner"></div> : <FancyComponent />;
}
Astro 包括几个内置的组件供你在你的项目中使用。在 .astro
文件中可以通过 import {} from 'astro/components';
引用所有的内置组件。
<Markdown />
Section titled <Markdown />Markdown 组件不再内置到 Astro 中。请在 Markdown 页面查看如何将 Markdown 导入 Astro 文件。
<Code />
Section titled <Code />---
import { Code } from 'astro/components';
---
<!-- 使用语法凸显部分 JavaScript 代码-->
<Code code={`const foo = 'bar';`} lang="js" />
<!-- 可选:定制你的主题 -->
<Code code={`const foo = 'bar';`} lang="js" theme="dark-plus" />
<!-- 可选:启用文字包装 -->
<Code code={`const foo = 'bar';`} lang="js" wrap />
该组件在构建时为代码块提供语法高亮(不包括客户端 JavaScript)。该组件由 Shiki 驱动,它支持所有流行的主题和语言。另外,你可以通过给 theme
和 lang
传递自定义主题和语言分别添加它们。
<Prism />
Section titled <Prism />---
import { Prism } from '@astrojs/prism';
---
<Prism lang="js" code={`const foo = 'bar';`} />
这个组件通过应用 Prism 的 CSS 类为代码块提供特定语言的语法高亮。注意,你需要提供 Prism 的 CSS 样式表(或用自己的),以启用语法高亮! 参见 Prism 配置部分了解更多细节。
参见 Prism 支持的语言列表,在那里你可以找到一种语言的对应别名。而且,你也可以用 lang="astro"
来展示 Astro 代码块!
<Debug />
Section titled <Debug />---
import { Debug } from 'astro/components';
const serverObject = {
a: 0,
b: "string",
c: {
nested: "object"
}
}
---
<Debug {serverObject} />
这个组件提供了无需 JavaScript 在客户端检查数值的方法。