API 参考

Astro 在所有 .astro 文件中均可用。它有以下功能:

Astro.glob() 可以在静态网站 setup 中加载本地文件:

./src/components/my-component.astro
---
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 文件有以下接口:

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 是一个包含任何作为组件属性传递的值的对象。.md.mdx 文件的布局组件接收作为参数的 frontmatter 值。

./src/components/Heading.astro
---
const { title, date } = Astro.props;
---
<div>
    <h1>{title}</h1>
    <p>{date}</p>
</div>
./src/pages/index.astro
---
import Heading from '../components/Heading.astro';
---
<Heading title="我的第一篇文章" date="09 Aug 2022" />

📚 进一步了解 Markdown 和 MDX 布局如何处理道具。

📚 了解如何为你的道具添加 Typescript 类型定义

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 是标准的 Request 对象。它可以用来获取请求的 urlheadersmethod,甚至是 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 是标准的 ResponseInit对象。它用于设置页面响应中的 statusstatusTextheaders

---
if(condition) {
  Astro.response.status = 404;
  Astro.response.statusText = 'Not found';
}
---

或者设置 header:

---
Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;');
---

当前页面的标准链接

添加于: v1.0.0-rc

URL对象,由当前 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} />
添加于: v1.0.0-rc

指定请求的 IP 地址。这个属性只在为 SSR(服务器端渲染)构建时可用,不应该用于静态网站。

---
const ip = Astro.clientAddress;
---

<div>你的 IP 地址是:<span class="address">{ ip }</span></div>

Astro.site 返回根据 Astro 配置中的 site 生成的 URL。如果没指定,将返回根据 localhost 生成的链接。

添加于: v1.0.0

Astro.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 包含修改 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 允许 Astro 组件被递归调用。这使得你可以通过在组件模板中使用 <Astro.self> 从自身内部渲染 Astro 组件。这对迭代大型数据存储和嵌套数据结构很有帮助。

NestedList.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() 函数。

必须要有该函数,因为 Astro 是静态站点生成器。这意味着整个网站是预构建的。如果 Astro 不知道在构建时生成什么页面,你的用户在访问你的网站时就看不到它。

---
export async function getStaticPaths() {
  return [
    { params: { /* 必需 */ }, props: { /* 可选 */ } },
    { params: { ... } },
    { params: { ... } },
    // ...
  ];
}
---
<!-- 你的 HTML 模板在这里 -->

getStaticPaths() 函数应该返回对象数组,以确定哪些路径会被 Astro 预渲染。

每个返回对象的 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/1posts/2posts/3

为了给每个生成的页面传递额外的数据,你也可以在每个返回的路径对象上设置 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/1posts/2。页面可以使用 Astro.props 引用这些数据。

分页是 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].astropage 参数将是链接中的页数。

  • /posts/[page].astro:会产生 /posts/1/posts/2/posts/3 等链接。
  • /posts/[...page].astro:将产生 /posts/posts/2 /posts/3 等链接。

分页会给每个渲染的页面传递 page 参数,代表分页集合中的单页数据。这包括你分页的数据(page.data)以及该页的元数据(page.urlpage.startpage.endpage.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

所有 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 组件不再内置到 Astro 中。请在 Markdown 页面查看如何将 Markdown 导入 Astro 文件

---
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 驱动,它支持所有流行的主题语言。另外,你可以通过给 themelang 传递自定义主题和语言分别添加它们。

---
import { Prism } from '@astrojs/prism';
---
<Prism lang="js" code={`const foo = 'bar';`} />

这个组件通过应用 Prism 的 CSS 类为代码块提供特定语言的语法高亮。注意,你需要提供 Prism 的 CSS 样式表(或用自己的),以启用语法高亮! 参见 Prism 配置部分了解更多细节。

参见 Prism 支持的语言列表,在那里你可以找到一种语言的对应别名。而且,你也可以用 lang="astro" 来展示 Astro 代码块!

---
import { Debug } from 'astro/components';
const serverObject = {
  a: 0,
  b: "string",
  c: {
    nested: "object"
  }
}
---
<Debug {serverObject} />

这个组件提供了无需 JavaScript 在客户端检查数值的方法。