首页 / Astro 教程 / 路由参数获取与页面状态

Astro 教程

路由参数获取与页面状态

本教程共 56 篇 · 第 16 篇 · 更新于 2026-08-07 · 约 11 分钟阅读

AstroAstro 教程Astro.paramsAstro.props重定向重写路由优先级500 错误页

本节目标:学会在页面里取出网址上的动态参数和传入的数据,并搞懂重定向、重写,以及多条路由抢同一个网址时谁优先。

前几章我们让文件变成了网址,也学会了用动态路由批量造网址。这一章解决「拿到网址之后」的事:页面代码里怎么读取参数?怎么知道当前是什么状态?出错时怎么处理?

用 Astro.params 取动态参数

在动态路由页面里,网址上那段方括号参数,靠 Astro.params 读取。它返回一个对象,键是参数名,值是网址里的对应片段。

// src/pages/books/[category]/[id].astro
---
const { category, id } = Astro.params;
---
<p>分类:{category},编号:{id}</p>

访问 /books/novel/42 时,category"novel"id"42"。就这么直接。

Note

Astro.params 里的值都是字符串。如果你的编号要当数字算,记得用 Number(id) 转换一下。

用 Astro.props 取传入的数据

上一章说过,getStaticPaths 除了 params 还能带 props。这些数据在页面里通过 Astro.props 拿,跟普通组件收属性一模一样。

// src/pages/posts/[slug].astro
---
export function getStaticPaths() {
  return [
    { params: { slug: "hello" }, props: { title: "你好", views: 128 } },
  ];
}

const { title, views } = Astro.props;
---
<h1>{title}</h1>
<p>浏览量:{views}</p>

params 决定网址,props 决定内容,两者在页面里分别从 Astro.paramsAstro.props 取,清清楚楚。

500 错误页能拿到错误状态

第 12 章提过,按需渲染模式下可以建 src/pages/500.astro 做自定义错误页。这个特殊页面会自动收到一个 error 属性,里面是被抛出的错误对象。

// src/pages/500.astro
---
interface Props {
  error: unknown;
}
const { error } = Astro.props;
---
<div>{error instanceof Error ? error.message : "未知错误"}</div>

通过 Astro.props.error,你能拿到出错信息,决定展示什么给访客。注意别把错误的完整堆栈(stack)直接显示出来,那会泄露服务器代码结构,有安全风险。

Warning

error 的类型是 unknown,所以判断它到底是不是 Error 实例再取 message,是更稳妥的写法。

重定向:把访客引到新网址

「重定向(redirect)」就是:访客点开旧网址,你把他自动送到新网址。常见原因有俩:网站改版、旧路径作废;或用户做了某个动作(比如登录成功)要跳去对应页面。

Astro 里重定向有两种:写在配置里的「配置式」,和代码里触发的「动态式」。

配置式重定向

astro.config.mjs 里用 redirects 写死一批映射:

// astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  redirects: {
    "/old-page": "/new-page",
    "/blog": "https://example.com/blog",
  },
});

左边的旧路径会永久跳到右边的新路径。从 Astro v5.2.0 起,也能跳到以 http/https 开头的外部网址。

Note

重定向的优先级低于同名的真实页面文件。也就是说,如果你配置了 /old-page 跳转到 /new-page,但项目里又存在 src/pages/old-page.astro,那访客访问时看到的是真实页面,不会跳转。

动态路由也能配重定向,只要新旧两边参数一致:

export default defineConfig({
  redirects: {
    "/blog/[...slug]": "/articles/[...slug]",
  },
});

在 SSR 或用静态适配器时,还可以用对象形式指定状态码:

export default defineConfig({
  redirects: {
    "/old-page": { status: 302, destination: "/new-page" },
  },
});

动态式重定向

有些跳转没法写死,得看运行时情况。比如「没登录就访问账号页,跳去登录页」,这要用 Astro.redirect()

// src/pages/account.astro
---
import { isLoggedIn } from "../utils";

const cookie = Astro.request.headers.get("cookie");

// 没登录就重定向到登录页
if (!isLoggedIn(cookie)) {
  return Astro.redirect("/login");
}
---

Astro.redirect() 返回一个响应,用 return 把它交出去,页面就跳走了。这种方式适合「根据条件临时决定跳哪」的场景。

Note

在按需渲染模式里,Astro 用了 HTML 流式输出,所以重定向必须放在页面顶层,不能写在子组件里。

重写:换内容不换网址

「重写(rewrite)」和重定向容易混,区别很关键:

  • 重定向:浏览器网址栏变成新地址,访客「真的去了另一个网址」。
  • 重写:浏览器网址栏不变,但显示的内容是另一个网址的。访客以为自己还在原地址。

重写适合「同一个内容想在多个路径展示」的场景,比如中古西班牙语 /es-cu/ 显示的其实是 /es/ 的内容:

// src/pages/es-cu/articles/introduction.astro
---
return Astro.rewrite("/es/articles/introduction");
---

Astro.rewrite() 时,如果目标网址不存在,会返回 404;如果目标运行时出错,开发环境显示错误浮层、生产环境返回 500。

你甚至可以故意重写到 404 页,用来表示「这个商品已下架」:

// src/pages/[item].astro
---
const { item } = Astro.params;

if (!itemExists(item)) {
  return Astro.rewrite("/404");
}
---
Tip

重定向改网址、重写留网址——记这一句就够了。SEO 和用户体验上,重写常用来避免无意义跳转或幽灵 404。

多条路由抢同一网址,谁优先

当不同文件都能生成同一个网址时(比如 /posts/create),Astro 得有个判定的顺序。规则从高到低是:

  1. Astro 保留路由:如 _astro/_server_islands/_actions/ 这些内部路由,永远最优先。
  2. 路径段多的胜出/posts/ 下的路由,优先于根目录的 /[...slug].astro
  3. 静态无参数路由胜出/posts/create.astro 优先于 /posts/[page].astro 等动态路由。
  4. 具名参数胜出/posts/[page].astro 优先于 /posts/[...slug].astro 这种剩余参数。
  5. 预渲染动态路由优先于服务端动态路由。
  6. 端点(endpoint) 优先于普通页面。
  7. 文件路由 优先于重定向。
  8. 以上都分不出,按 Node 默认语言环境的字母序排。

举个具体例子,下面这些文件都可能影响 /posts/create

src/pages/
├── [...slug].astro
└── posts/
    ├── create.astro
    ├── [page].astro
    └── [...slug].astro

结果:/posts/createposts/create.astro 生成;/posts/1/posts/2posts/[page].astro 生成;/posts/1/2 这种深层路径才轮到 posts/[...slug].astro;而根目录的 [...slug].astro 只接管 /abc/xyz 这些跟 posts 无关的网址。

Note

初学者不必死记顺序。记住一句话就够:「写死的、具体的,胜过通配的、模糊的。」真遇到冲突,看构建日志或实际访问验证即可。

一个排错小建议

路由相关问题最常被问到的,是「我明明写了文件,为啥 404?」多数时候原因就这几个:

  • 文件没放在 src/pages/ 目录下,Astro 根本不认它。
  • 用了下划线 _ 开头,文件被排除出路由了。
  • 动态路由在静态模式下忘了写 getStaticPaths,构建时没生成对应网址。
  • 链接 href 写成了相对文件路径,而不是相对网站根目录的网址。

按这四条逐一排查,大部分路由谜题都能解开。

本章小结

这一章把「网址生成之后」的关键能力补齐了:用 Astro.params 取动态参数,用 Astro.propsgetStaticPaths 传来的数据,用 error 属性在 500 页里拿错误状态。重定向(Astro.redirect 与配置式 redirects)会改网址,重写(Astro.rewrite)保留网址却换内容。多条路由冲突时,具体的、写死的优先于通配的。

到此,Astro 的页面与路由主线就讲完了。后面我们会进入内容、样式、图片、群岛架构等更精彩的主题。