Astro 渲染上下文
渲染页面时,Astro 提供了特定于当前渲染的运行时 API。这包括很多有用的信息,例如当前页面的 URL,以及执行操作(如重定向到另一个页面)的 API。
在 .astro 组件中,这个上下文可以从 Astro 全局对象中获取。端点函数也会以这个相同的上下文对象作为它们的第一个参数被调用,其属性与 Astro 全局属性相同。
某些属性仅在按需渲染的路由上可用,或在预渲染页面上功能有限。
Astro 全局对象在所有 .astro 文件中都可用。在 端点函数 中使用 context 对象来提供静态服务或实时服务器端点,在 中间件 中注入页面或端点即将渲染时的行为。
上下文对象
段落标题 上下文对象以下属性可用于 Astro 全局对象(例如 Astro.props、Astro.redirect())以及传递给端点函数和中间件的上下文对象(例如 context.props、context.redirect())。
props
段落标题 propsprops 是一个对象,包含了作为 组件参数 传递的任何值。
---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
段落标题 paramsparams 是一个对象,包含了请求匹配的动态路由段的值。它的键必须与页面或端点文件路径中的 参数 匹配。
在静态构建中,这将是 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
段落标题 url类型: 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} />site
段落标题 site类型: 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
段落标题 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
段落标题 isPrerendered类型: boolean
astro@5.0.0
表示当前页面是否预渲染的布尔值。
你可以使用此属性在中间件中运行条件逻辑,例如,以避免访问预渲染页面中的标头。
generator
段落标题 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
段落标题 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
段落标题 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()
段落标题 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()
段落标题 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
段落标题 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
段落标题 preferredLocale类型: string | undefined
astro@3.5.0
preferredLocale 是一个计算值,用于找到访问者的浏览器语言首选项和你的站点支持的语言环境之间的最佳匹配。
它通过检查 i18n.locales 数组中配置的语言环境和用户浏览器支持的语言环境(通过 Accept-Language 头)来计算。如果没匹配到,则该值为 undefined。
此属性仅适用于按需渲染的路由,不能在预渲染的静态页面上使用。
preferredLocaleList
段落标题 preferredLocaleList类型: string[] | undefined
astro@3.5.0
preferredLocaleList 表示浏览器请求的所有语言环境和你的网站支持的所有语言环境之间的兼容语言列表。这将生成你的网站和访问者之间所有兼容语言的列表。
如果在你的 locales 数组中找不到浏览器请求的任何语言,则该值为 []。这发生在你不支持访问者的任何首选语言时。
如果你的浏览器没有指定任何首选语言,那么这个值将是 i18n.locales:所有支持的语言环境将被认为是访问者没有首选项的首选语言。
此属性仅适用于按需渲染的路由,不能在预渲染的静态页面上使用。
currentLocale
段落标题 currentLocale类型: string | undefined
astro@3.5.6
使用你的 locales 配置中指定的语法从当前 URL 计算的语言环境。如果 URL 不包含 /[locale]/ 前缀,则该值将默认为 i18n.defaultLocale。
getActionResult()
段落标题 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()
段落标题 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
段落标题 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
段落标题 cookies类型: AstroCookies
astro@1.4.0
cookies 包含用于读取和操作 按需渲染的路由 的 cookie 的工具函数。
Cookie 工具函数
段落标题 Cookie 工具函数cookies.get()
段落标题 cookies.get()类型: (key: string, options?: AstroCookieGetOptions) => AstroCookie | undefined
获取 cookie 作为 AstroCookie 对象,其中包含 value 和将 cookie 转换为非字符串类型的工具函数。
cookies.has()
段落标题 cookies.has()类型: (key: string, options?: AstroCookieGetOptions) => boolean
检查 cookie 是否存在。如果 cookie 是通过 Astro.cookies.set() 设置的,这将返回 true,否则,它将检查 Astro.request 中的 cookie。
cookies.set()
段落标题 cookies.set()类型: (key: string, value: string | object, options?: AstroCookieSetOptions) => void
设置 cookie key 为给定的值。这将尝试将 cookie 值转换为字符串。选项提供了设置 cookie 特性 的方法,例如 maxAge 或 httpOnly。
cookies.delete()
段落标题 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()
段落标题 cookies.merge()类型: (cookies: AstroCookies) => void
将新的 AstroCookies 实例合并到当前实例中。任何新 cookie 将被添加到当前实例中,任何具有相同名称的 cookie 将覆盖现有值。
cookies.headers()
段落标题 cookies.headers()类型: () => Iterator<string>
获取将与响应一起发送的 Set-Cookie 的标头值。
AstroCookie 类型
段落标题 AstroCookie 类型通过 Astro.cookies.get() 获取 cookie 返回的类型。它具有以下属性:
value
段落标题 value类型: string
cookie 的原始字符串值。
json
段落标题 json类型: () => Record<string, any>
通过 JSON.parse() 解析 cookie 值,返回一个对象。如果 cookie 值不是有效的 JSON,则抛出异常。
number
段落标题 number类型: () => number
将 cookie 值解析为数字。如果不是有效的数字,则返回 NaN。
boolean
段落标题 boolean类型: () => boolean
将 cookie 值转换为布尔值。
AstroCookieGetOptions
段落标题 AstroCookieGetOptions
添加于:
astro@4.1.0
AstroCookieGetOption 接口允许你在获取 cookie 时指定选项。
decode
段落标题 decode类型: (value: string) => string
允许自定义 cookie 反序列化为值的方式。
AstroCookieSetOptions
段落标题 AstroCookieSetOptions
添加于:
astro@4.1.0
AstroCookieSetOptions 是一个对象,可以在设置 cookie 时传递给 Astro.cookies.set(),以自定义 cookie 的序列化方式。
domain
段落标题 domain类型: string
指定 domain。如果未设置 domain,大多数客户端将解释为应用于当前域。
expires
段落标题 expires类型: Date
指定 cookie 过期的日期。
httpOnly
段落标题 httpOnly类型: boolean
如果设置为 true,则 cookie 将不会在客户端上可访问。
maxAge
段落标题 maxAge类型: number
指定一个以秒为单位的数字,表示 cookie 有效的时间。
path
段落标题 path类型: string
指定 cookie 应用的域的子路径。
sameSite
段落标题 sameSite类型: boolean | 'lax' | 'none' | 'strict'
指定 SameSite cookie 标头的值。
secure
段落标题 secure类型: boolean
如果为 true,则 cookie 仅在 https 站点上设置。
encode
段落标题 encode类型: (value: string) => string
允许自定义 cookie 序列化为值的方式。
session
段落标题 session类型: AstroSession
astro@5.7.0
session 是一个允许在 按需渲染路由 的多个请求间存储数据的对象。其通过一个仅包含会话 ID 的 Cookie 实现关联,数据本身并不存储于 Cookie 中。
会话(session)会在首次被使用时自动创建,并设置对应的会话 Cookie。如果未配置会话存储,又或者是当前路由为预渲染模式,session 对象都会是 undefined,当你尝试访问时,日志将会记录错误。
有关如何在你的 Astro 项目中使用会话,请参阅 会话指南 以获取更多信息。
get()
段落标题 get()类型: (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 });}set()
段落标题 set()类型: (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()
段落标题 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()
段落标题 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()
段落标题 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 });};废弃的对象属性
段落标题 废弃的对象属性Astro.glob()
段落标题 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 文件
段落标题 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 文件
段落标题 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');---