Astro 渲染上下文
渲染页面时,Astro 提供了特定于当前渲染的运行时 API。这包括很多有用的信息,例如当前页面的 URL,以及执行操作(如重定向到另一个页面)的 API。
在 .astro
组件中,这个上下文可以从 Astro
全局对象中获取。端点函数也会以这个相同的上下文对象作为它们的第一个参数被调用,其属性与 Astro 全局属性相同。
某些属性仅在按需渲染的路由上可用,或在预渲染页面上功能有限。
Astro
全局对象在所有 .astro
文件中都可用。在 端点函数 中使用 context
对象来提供静态服务或实时服务器端点,在 中间件 中注入页面或端点即将渲染时的行为。
以下属性可用于 Astro
全局对象(例如 Astro.props
、Astro.redirect()
)以及传递给端点函数和中间件的上下文对象(例如 context.props
、context.redirect()
)。
props
是一个对象,包含了作为 组件参数 传递的任何值。
---const { title, date } = Astro.props;---<div> <h1>{title}</h1> <p>{date}</p></div>
---import Heading from '../components/Heading.astro';---<Heading title="My First Post" date="09 Aug 2022" />
props
对象还包含从 getStaticPaths()
传递的任何 props
,用于渲染静态路由。
---export function getStaticPaths() { return [ { params: { id: '1' }, props: { author: 'Blu' } }, { params: { id: '2' }, props: { author: 'Erika' } }, { params: { id: '3' }, props: { author: 'Matthew' } } ];}
const { id } = Astro.params;const { author } = Astro.props;---
import type { APIContext } from 'astro';
export function getStaticPaths() { return [ { params: { id: '1' }, props: { author: 'Blu' } }, { params: { id: '2' }, props: { author: 'Erika' } }, { params: { id: '3' }, props: { author: 'Matthew' } } ];}
export function GET({ props }: APIContext) { return new Response( JSON.stringify({ author: props.author }), );}
params
Section titled “params”params
是一个对象,包含了请求匹配的动态路由段的值。它的键必须与页面或端点文件路径中的 参数 匹配。
在静态构建中,这将是 getStaticPaths()
返回的 params
,用于预渲染 动态路由:
---export function getStaticPaths() { return [ { params: { id: '1' } }, { params: { id: '2' } }, { params: { id: '3' } } ];}const { id } = Astro.params;---<h1>{id}</h1>
import type { APIContext } from 'astro';
export function getStaticPaths() { return [ { params: { id: '1' } }, { params: { id: '2' } }, { params: { id: '3' } } ];}
export function GET({ params }: APIContext) { return new Response( JSON.stringify({ id: params.id }), );}
当按需渲染路由时,params
可以是与动态路由模式中的路径段匹配的任何值。
---import { getPost } from '../api';
const post = await getPost(Astro.params.id);
// 没有找到匹配 ID 的文章if (!post) { return Astro.redirect("/404")}---<html> <h1>{post.name}</h1></html>
另见:params
类型: URL
astro@1.0.0
url
是一个从当前 request.url
值构造的 URL 对象。它对于与请求 URL 的各个属性进行交互非常有用,例如 pathname 和 origin。
Astro.url
相当于 new URL(Astro.request.url)
。
在开发模式下 url
是一个 localhost
URL。在构建站点时,预渲染路由将根据 site
和 base
选项生成 URL。如果未配置 site
,构建期间预渲染页面将收到 localhost
URL。
<h1>当前 URL 是:{Astro.url}</h1><h1>当前 URL 的 pathname 是:{Astro.url.pathname}</h1><h1>当前 URL 的 origin 是:{Astro.url.origin}</h1>
你还可以使用 url
通过将其作为参数传递给 new URL()
来创建新的 URL。
---// 示例:使用你的生产域名构建一个规范 URLconst canonicalURL = new URL(Astro.url.pathname, Astro.site);// 示例:使用你的当前域名构建 SEO meta 标签的 URLconst socialImageURL = new URL('/images/preview.png', Astro.url);---<link rel="canonical" href={canonicalURL} /><meta property="og:image" content={socialImageURL} />
类型: URL | undefined
site
是一个从你的 Astro 配置中的 site
构造的 URL
。如果你没有在 Astro 配置中设置 site
的值,它将返回 undefined
。
<link rel="alternate" type="application/rss+xml" title="网站标题" href={new URL("rss.xml", Astro.site)}/>
clientAddress
Section titled “clientAddress”类型: string
astro@1.0.0
clientAddress
指定请求的 IP 地址。此属性仅适用于按需渲染的路由,不能在预渲染页面上使用。
---export const prerender = false; // 'server' 模式下不需要---
<div>Your IP address is: <span class="address">{Astro.clientAddress}</span></div>
export const prerender = false; // 'server' 模式下不需要import type { APIContext } from 'astro';
export function GET({ clientAddress }: APIContext) { return new Response(`Your IP address is: ${clientAddress}`);}
isPrerendered
Section titled “isPrerendered”类型: boolean
astro@5.0.0
表示当前页面是否预渲染的布尔值。
你可以使用此属性在中间件中运行条件逻辑,例如,以避免访问预渲染页面中的标头。
generator
Section titled “generator”类型: string
astro@1.0.0
generator
提供了你的项目当前运行的 Astro 版本。这是一个方便的方法,可以使用你当前的 Astro 版本添加一个 <meta name="generator">
标签。它遵循格式 "Astro v5.x.x"
。
<html> <head> <meta name="generator" content={Astro.generator} /> </head> <body> <footer> <p>Built with <a href="https://astro.build">{Astro.generator}</a></p> </footer> </body></html>
import type { APIContext } from 'astro';
export function GET({ generator, site }: APIContext) { const body = JSON.stringify({ generator, site }); return new Response(body);}
request
Section titled “request”类型: Request
request
是一个标准的 Request 对象。它可以用于获取请求的 url
、headers
、method
,甚至请求的 body。
<p>收到一个 {Astro.request.method} 请求到 "{Astro.request.url}".</p><p>收到请求的 headers:</p><p><code>{JSON.stringify(Object.fromEntries(Astro.request.headers))}</code></p>
import type { APIContext } from 'astro';
export function GET({ request }: APIContext) { return new Response(`Hello ${request.url}`);}
在预渲染页面上,request.url
不包含搜索参数,如 ?type=new
,因为在静态构建期间无法提前确定它们。然而,在按需渲染的页面上,request.url
包含搜索参数,因为它们可以从服务器请求中确定。
response
Section titled “response”类型: ResponseInit & { readonly headers: Headers }
response
是一个标准的 ResponseInit
对象。它有以下结构。
status
:响应的状态码,例如200
。statusText
:与状态码关联的状态消息,例如'OK'
。headers
:可用于设置响应的 HTTP 头的Headers
实例。
Astro.response
常用于为页面的响应设置 status
、statusText
和 headers
。
---if (condition) { Astro.response.status = 404; Astro.response.statusText = 'Not found';}---
或者设置一个标头:
---Astro.response.headers.set('Set-Cookie', 'a=b; Path=/;');---
redirect()
Section titled “redirect()”类型: (path: string, status?: number) => Response
astro@1.5.0
redirect()
返回一个 Response 对象,允许你重定向到另一个页面,并可选地提供一个 HTTP 响应状态码 作为第二个参数。
页面(而不是子组件)必须 return
Astro.redirect()
的结果才能进行重定向。
对于静态生成的路由,这将使用 <meta http-equiv="refresh">
标签 进行客户端重定向,不支持状态码。
对于动态渲染的路由,支持在重定向时设置自定义状态码。如果未指定,重定向将使用 302
状态码。
下面是一个将用户重定向到登录页面的示例:
---import { isLoggedIn } from '../utils';
const cookie = Astro.request.headers.get('cookie');
// 如果用户未登录,则将其重定向到登录页面if (!isLoggedIn(cookie)) { return Astro.redirect('/login');}---
<p>用户信息</p>
import type { APIContext } from 'astro';
export function GET({ redirect, request }: APIContext) { const cookie = request.headers.get('cookie'); if (!isLoggedIn(cookie)) { return redirect('/login', 302); } else { // 返回用户信息 }}
rewrite()
Section titled “rewrite()”类型: (rewritePayload: string | URL | Request) => Promise<Response>
astro@4.13.0
rewrite()
允许你在不重定向浏览器到新页面的情况下从不同的 URL 或路径提供内容。
此方法接受一个字符串、一个 URL
或一个 Request
作为路径的位置。
使用字符串提供显式路径:
---return Astro.rewrite("/login")---
import type { APIContext } from 'astro';
export function GET({ rewrite }: APIContext) { return rewrite('/login');}
当你需要构造重写的 URL 路径时,使用 URL
类型。下面的示例通过从相对路径 "../"
创建一个新的 URL 来渲染页面的父路径:
---return Astro.rewrite(new URL("../", Astro.url))---
import type { APIContext } from 'astro';
export function GET({ rewrite }: APIContext) { return rewrite(new URL("../", Astro.url));}
使用 Request
类型完全控制发送到新路径的服务器的 Request
。以下示例发送一个请求以渲染父页面,同时提供 headers:
---return Astro.rewrite(new Request(new URL("../", Astro.url), { headers: { "x-custom-header": JSON.stringify(Astro.locals.someValue) }}))---
import type { APIContext } from 'astro';
export function GET({ rewrite }: APIContext) { return rewrite(new Request(new URL("../", Astro.url), { headers: { "x-custom-header": JSON.stringify(Astro.locals.someValue) } }));}
locals
Section titled “locals”
添加于:
astro@2.4.0
locals
是一个对象,用于在请求的生命周期中存储和访问任意信息。Astro.locals
是一个包含由中间件设置的 context.locals
对象中的任何值的对象。使用它在 .astro
文件中访问中间件返回的数据。
中间件函数可以读取和写入 context.locals
的值:
import type { MiddlewareHandler } from 'astro';
export const onRequest: MiddlewareHandler = ({ locals }, next) => { if (!locals.title) { locals.title = "Default Title"; } return next();}
Astro 组件和 API 端点可以在渲染时从 locals
中读取值:
---const title = Astro.locals.title;---<h1>{title}</h1>
import type { APIContext } from 'astro';
export function GET({ locals }: APIContext) { return new Response(locals.title); // "Default Title"}
preferredLocale
Section titled “preferredLocale”类型: string | undefined
astro@3.5.0
preferredLocale
是一个计算值,用于找到访问者的浏览器语言首选项和你的站点支持的语言环境之间的最佳匹配。
它通过检查 i18n.locales
数组中配置的语言环境和用户浏览器支持的语言环境(通过 Accept-Language
头)来计算。如果没匹配到,则该值为 undefined
。
此属性仅适用于按需渲染的路由,不能在预渲染的静态页面上使用。
preferredLocaleList
Section titled “preferredLocaleList”类型: string[] | undefined
astro@3.5.0
preferredLocaleList
表示浏览器请求的所有语言环境和你的网站支持的所有语言环境之间的兼容语言列表。这将生成你的网站和访问者之间所有兼容语言的列表。
如果在你的 locales 数组中找不到浏览器请求的任何语言,则该值为 []
。这发生在你不支持访问者的任何首选语言时。
如果你的浏览器没有指定任何首选语言,那么这个值将是 i18n.locales
:所有支持的语言环境将被认为是访问者没有首选项的首选语言。
此属性仅适用于按需渲染的路由,不能在预渲染的静态页面上使用。
currentLocale
Section titled “currentLocale”类型: string | undefined
astro@3.5.6
使用你的 locales
配置中指定的语法从当前 URL 计算的语言环境。如果 URL 不包含 /[locale]/
前缀,则该值将默认为 i18n.defaultLocale
。
getActionResult()
Section titled “getActionResult()”类型: (action: TAction) => ActionReturnType<TAction> | undefined
astro@4.15.0
getActionResult()
是一个函数,用于返回 Action 提交的结果。它接受一个 Action 函数作为参数(例如 actions.logout
),并在接收到提交时返回一个 data
或 error
对象。否则,它将返回 undefined
。
---import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.logout);---
<form action={actions.logout}> <button type="submit">登出</button></form>{result?.error && <p>登出失败。请重试。</p>}
callAction()
Section titled “callAction()”
添加于:
astro@4.15.0
callAction()
是一个用于直接从你的 Astro 组件调用 Action 处理程序的函数。它接受一个 Action 函数作为第一个参数(例如 actions.logout
),并将 action 接收的任何输入作为第二个参数。它将 action 的结果作为一个 promise 返回。
---import { actions } from 'astro:actions';
const { data, error } = await Astro.callAction(actions.logout, { userId: '123' });---
routePattern
Section titled “routePattern”类型: string
astro@5.0.0
路由模式负责生成当前页面或路由。在基于文件的路由中,这类似于用于创建路由的项目中的文件路径。当集成为你的项目创建路由时,context.routePattern
与 injectRoute.pattern
的值相同。
该值将以斜杠开头,并类似于相对于 src/pages/
文件夹的页面组件的路径,不包括文件扩展名。
例如,文件 src/pages/en/blog/[slug].astro
将返回 /en/blog/[slug]
作为 routePattern
。该文件生成的站点上的每个页面(例如 /en/blog/post-1/
、/en/blog/post-2/
等)都共享相同的 routePattern
值。对于 index.*
路由,路由模式不会包含单词 “index.” 例如,src/pages/index.astro
将返回 /
。
你可以使用这个属性来了解哪个路由正在渲染你的组件。这使你可以将类似生成的页面 URL 一起进行定位或分析。例如,你可以使用它来有条件地渲染某些信息,或收集关于哪些路由速度较慢的指标。
cookies
Section titled “cookies”类型: AstroCookies
astro@1.4.0
cookies
包含用于读取和操作 按需渲染的路由 的 cookie 的工具函数。
Cookie 工具函数
Section titled “Cookie 工具函数”cookies.get()
Section titled “cookies.get()”类型: (key: string, options?: AstroCookieGetOptions) => AstroCookie | undefined
获取 cookie 作为 AstroCookie
对象,其中包含 value
和将 cookie 转换为非字符串类型的工具函数。
cookies.has()
Section titled “cookies.has()”类型: (key: string, options?: AstroCookieGetOptions) => boolean
检查 cookie 是否存在。如果 cookie 是通过 Astro.cookies.set()
设置的,这将返回 true
,否则,它将检查 Astro.request
中的 cookie。
cookies.set()
Section titled “cookies.set()”类型: (key: string, value: string | object, options?: AstroCookieSetOptions) => void
设置 cookie key
为给定的值。这将尝试将 cookie 值转换为字符串。选项提供了设置 cookie 特性 的方法,例如 maxAge
或 httpOnly
。
cookies.delete()
Section titled “cookies.delete()”类型: (key: string, options?: AstroCookieDeleteOptions) => void
通过将过期日期设置为过去(Unix 时间中的 0)来使 cookie 失效。
一旦 cookie 被 “删除”(过期),Astro.cookies.has()
将返回 false
,Astro.cookies.get()
将返回一个 value
为 undefined
的 AstroCookie
。删除 cookie 时可用的选项有:domain
、path
、httpOnly
、sameSite
和 secure
。
cookies.merge()
Section titled “cookies.merge()”类型: (cookies: AstroCookies) => void
将新的 AstroCookies
实例合并到当前实例中。任何新 cookie 将被添加到当前实例中,任何具有相同名称的 cookie 将覆盖现有值。
cookies.headers()
Section titled “cookies.headers()”类型: () => Iterator<string>
获取将与响应一起发送的 Set-Cookie
的标头值。
AstroCookie
类型
Section titled “AstroCookie 类型”通过 Astro.cookies.get()
获取 cookie 返回的类型。它具有以下属性:
类型: string
cookie 的原始字符串值。
类型: () => Record<string, any>
通过 JSON.parse()
解析 cookie 值,返回一个对象。如果 cookie 值不是有效的 JSON,则抛出异常。
number
Section titled “number”类型: () => number
将 cookie 值解析为数字。如果不是有效的数字,则返回 NaN。
boolean
Section titled “boolean”类型: () => boolean
将 cookie 值转换为布尔值。
AstroCookieGetOptions
Section titled “AstroCookieGetOptions”
添加于:
astro@4.1.0
AstroCookieGetOption
接口允许你在获取 cookie 时指定选项。
decode
Section titled “decode”类型: (value: string) => string
允许自定义 cookie 反序列化为值的方式。
AstroCookieSetOptions
Section titled “AstroCookieSetOptions”
添加于:
astro@4.1.0
AstroCookieSetOptions
是一个对象,可以在设置 cookie 时传递给 Astro.cookies.set()
,以自定义 cookie 的序列化方式。
domain
Section titled “domain”类型: string
指定 domain。如果未设置 domain,大多数客户端将解释为应用于当前域。
expires
Section titled “expires”类型: Date
指定 cookie 过期的日期。
httpOnly
Section titled “httpOnly”类型: boolean
如果设置为 true
,则 cookie 将不会在客户端上可访问。
maxAge
Section titled “maxAge”类型: number
指定一个以秒为单位的数字,表示 cookie 有效的时间。
类型: string
指定 cookie 应用的域的子路径。
sameSite
Section titled “sameSite”类型: boolean | 'lax' | 'none' | 'strict'
指定 SameSite cookie 标头的值。
secure
Section titled “secure”类型: boolean
如果为 true
,则 cookie 仅在 https 站点上设置。
encode
Section titled “encode”类型: (value: string) => string
允许自定义 cookie 序列化为值的方式。
session
Section titled “session”类型: AstroSession
astro@5.7.0
session
是一个允许在 按需渲染路由 的多个请求间存储数据的对象。其通过一个仅包含会话 ID 的 Cookie 实现关联,数据本身并不存储于 Cookie 中。
会话(session)会在首次被使用时自动创建,并设置对应的会话 Cookie。如果未配置会话存储,又或者是当前路由为预渲染模式,session
对象都会是 undefined
,当你尝试访问时,日志将会记录错误。
有关如何在你的 Astro 项目中使用会话,请参阅 会话指南 以获取更多信息。
类型: (key: string) => Promise<any>
返回会话中给定键的值。如果该键不存在,则返回 undefined
。
---const cart = await Astro.session?.get('cart');---<button>🛒 {cart?.length}</button>
import type { APIContext } from 'astro';
export async function GET({ session }: APIContext) { const cart = await session.get('cart'); return Response.json({ cart });}
类型: (key: string, value: any, options?: { ttl: number }) => void
设置会话中给定键的值。该值可以是任何可序列化类型。该方法是同步的,该值可立即用于检索,但是直到请求结束之前,该方法才能保存到后端。
---const { slug } = Astro.params;Astro.session?.set('lastViewedProduct', slug);---
import type { APIContext } from 'astro';
export async function POST({ session, request }: APIContext) { const cart = await session.get('cart'); const newItem = await request.json(); cart.push(newItem); // 保存更新后的购物车至会话 session.set('cart', cart); return Response.json({ cart });}
regenerate()
Section titled “regenerate()”类型: () => void
重新生成会话 ID。最佳实践是在用户登录或升级权限时调用此方法,以防止会话固定攻击。
---Astro.session?.regenerate();---
import type { APIContext } from 'astro';
export async function POST({ session }: APIContext) { // 对用户进行身份验证... doLogin(); // 重新生成会话 ID 以防止会话固定攻击 session.regenerate(); return Response.json({ success: true });}
destroy()
Section titled “destroy()”类型: () => void
销毁会话,从后端删除 Cookie 和对象。当用户退出登录或会话无效时应调用此方法。
---Astro.session?.destroy();return Astro.redirect('/login');---
import type { APIContext } from 'astro';
export async function POST({ session }: APIContext) { session.destroy(); return Response.json({ success: true });}
load()
Section titled “load()”类型: (id: string) => Promise<void>
通过 ID 来加载会话。在正常使用中,会话将自动从请求 Cookie 加载,但该方法可用于从其他 ID 来加载会话。如果你打算自己处理会话 ID,又或者你想在不使用 cookie 的情况下跟踪会话,该方法非常有效。
---// 从请求头而不是 Cookie 加载会话const sessionId = Astro.request.headers.get('x-session-id');await Astro.session?.load(sessionId);const cart = await Astro.session?.get('cart');---<h1>你的购物车</h1><ul> {cart?.map((item) => ( <li>{item.name}</li> ))}</ul>
import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ session, request }) => { // 从请求头而不是 Cookie 加载会话 const sessionId = request.headers.get('x-session-id'); await session.load(sessionId); const cart = await session.get('cart'); return Response.json({ cart });};
废弃的对象属性
Section titled “废弃的对象属性”Astro.glob()
Section titled “Astro.glob()”使用 Vite 的 import.meta.glob
查询项目文件。
Astro.glob('../pages/post/*.md')
可以替换为:
Object.values(import.meta.glob('../pages/post/*.md', { eager: true }));
更多信息和用法请参阅 导入指南。
Astro.glob()
是一种将许多本地文件加载到你的静态站点设置中的方法。
---const posts = await Astro.glob('../pages/post/*.md'); // 返回位于 ./src/pages/post/*.md 中的文章数组。---
<div>{posts.slice(0, 3).map((post) => ( <article> <h2>{post.frontmatter.title}</h2> <p>{post.frontmatter.description}</p> <a href={post.url}>Read more</a> </article>))}</div>
.glob()
只有一个参数:你想导入的本地文件相对 glob URL。它是异步的,并返回匹配文件的导出数组。
.glob()
不接受变量或字符串插值,因为它们无法静态分析。 (请参阅 导入指南 了解解决方法。) 这是因为 Astro.glob()
是 Vite 的 import.meta.glob()
的封装。
你可以在你的 Astro 项目中使用 import.meta.glob()
本身。你可能想在以下情况下这样做:
- 你需要在不是
.astro
文件的文件中使用此功能,例如 API 路由。Astro.glob()
仅在.astro
文件中可用,而import.meta.glob()
可在项目中的任何地方使用。 - 你不想立即加载每个文件。
import.meta.glob()
可以返回导入文件内容的函数,而不是返回内容本身。请注意,此导入包括所有导入文件的样式和脚本。这些将被打包并添加到页面中,无论文件是否实际使用,因为这是通过静态分析决定的,而不是在运行时决定的。 - 你想要访问每个文件的路径。
import.meta.glob()
返回文件路径到内容的映射,而Astro.glob()
返回内容列表。 - 你想要传递多个模式;例如,你想要添加一个 “负模式”,用于过滤掉某些文件。
import.meta.glob()
可以选择接受一个 glob 字符串数组,而不是一个字符串。
在 Vite 文档 中阅读更多。
Markdown 文件
Section titled “Markdown 文件”使用 Astro.glob()
加载的 Markdown 文件返回以下 MarkdownInstance
接口:
export interface MarkdownInstance<T extends Record<string, any>> { /* 在此文件的 YAML/TOML frontmatter 中指定的任何数据 */ frontmatter: T; /* 该文件的文件绝对路径 */ file: string; /* 该文件的渲染路径 */ url: string | undefined; /* 渲染此文件内容的 Astro 组件 */ Content: AstroComponentFactory; /** (仅限 Markdown) Markdown 文件的原始内容,不包括布局 HTML 和 YAML/TOML frontmatter */ rawContent(): string; /* (仅限 Markdown) Markdown 文件编译后的 HTML,不包括布局 HTML */ compiledContent(): string; /* 返回该文件中 h1...h6 元素数组的函数 */ getHeadings(): Promise<{ depth: number; slug: string; text: string }[]>; default: AstroComponentFactory;}
你可以选择使用 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 文件
Section titled “Astro 文件”Astro 文件具有以下接口:
export interface AstroInstance { /* 此文件的文件路径 */ file: string; /* 此文件的 URL(如果它在 pages 目录中)*/ url: string | undefined; default: AstroComponentFactory;}
其他文件可能有各种不同的接口,但如果你不知道文件类型包含什么,那么 Astro.glob()
可以接受 TypeScript 泛型。
---interface CustomDataFile { default: Record<string, any>;}const data = await Astro.glob<CustomDataFile>('../data/**/*.js');---