
本文详解 Next.js 中通过按钮或链接跳转至动态路由页面的正确方法,涵盖 Link 组件使用、动态路由文件命名规范、服务端获取参数(params)以及常见 404 错误的规避策略。
本文详解 next.js 中通过按钮或链接跳转至动态路由页面的正确方法,涵盖 `link` 组件使用、动态路由文件命名规范、服务端获取参数(`params`)以及常见 404 错误的规避策略。
在 Next.js 应用中(如宠物领养平台),实现按钮点击跳转到详情页是核心交互需求。但许多初学者会因路由配置不匹配或参数传递方式错误而遭遇 404 页面未找到 错误。根本原因通常在于:动态路由路径未正确定义、Link 的 href 与文件系统路径不一致,或服务端页面未正确接收路由参数。
✅ 正确做法:遵循 App Router 动态路由约定
Next.js(v13+,推荐使用 App Router)要求动态路由通过方括号语法定义文件夹名。若希望访问 /adote/123,则对应页面文件必须位于:
app/adote/[petId]/page.tsx
⚠️ 注意:不是 app/[petId]/page.tsx,也不是 app/adote/[petId].tsx —— 必须是 文件夹 + page.tsx 结构,且文件夹名严格匹配 href 中的动态段(如 [petId] 对应 /adote/[petId])。
? 前端跳转:使用 包裹按钮(推荐)
在 PetCard 组件中,直接将 href 设为 /adote/${pet.id},无需 as 或 passHref(这些属于旧版 pages 路由的遗留写法):
基于三引擎设计,从微信文章、新闻和博客网页提取干净内容,支持标题作者日期元数据,多格式和批量处理。
import Link from 'next/link';
import Button from '../components/Button';
export default function PetCard({ pet }) {
return (
<div classname="flex flex-col border p-4 rounded-lg hover:shadow-lg transition-shadow bg-white">
<link href="%7B%60/adote/%24%7Bpet.id%7D%60%7D">
<button label="Ver perfil" classname="bg-indigo-500 hover:bg-gray-600 focus-visible:outline-indigo-600 w-32 flex flex-row justify-center items-center"></button>
</div>
);
}
✅ 优势:
- 自动预加载目标页面(提升性能);
- 无刷新导航(SPA 体验);
- 语义化 标签生成,利于 SEO 和可访问性。
? 后端接收:通过 params 解构获取 ID
PetDetailPage 必须是 Server Component(默认行为),并接收 params 属性:
// app/adote/[petId]/page.tsx
import { notFound } from 'next/navigation';
// 模拟数据获取函数(实际中可调用 API 或数据库)
async function getPetDetails(id: string) {
// 示例:替换为真实 fetch 或 ORM 查询
const res = await fetch(`https://mockID.mockapi.io/pets/${id}`);
if (!res.ok) throw new Error('Pet not found');
return res.json();
}
export default async function PetDetailPage({ params }: { params: { petId: string } }) {
const pet = await getPetDetails(params.petId);
return (
<div classname="p-4 max-w-3xl mx-auto">
@@##@@
<h1 classname="text-2xl font-bold mt-4">{pet.name}</h1>
<p classname="text-gray-600">{pet.breed}</p>
<p classname="text-gray-600">Id: {pet.id}</p>
<p classname="text-gray-600">Idade: {pet.age}</p>
<p classname="text-gray-600">Gênero: {pet.gender}</p>
<p classname="mt-2">{pet.description}</p>
</div>
);
}
? 关键点:
- params 是 Next.js 自动注入的 prop,其属性名(如 petId)必须与动态文件夹名 [petId] 完全一致;
- 使用 async/await 直接在 Server Component 中获取数据,避免客户端水合问题;
- 添加错误处理(如 notFound() 或 try/catch)提升健壮性。
❌ 常见错误与修复
| 错误现象 | 原因 | 修复方案 |
|---|---|---|
| 404 This page could not be found | app/adote/[petId]/page.tsx 文件不存在,或文件夹名拼写错误(如 [petid]) | 检查路径是否严格为 app/adote/[petId]/page.tsx,大小写敏感 |
| 点击无反应或跳转失败 | 使用了 useRouter().push() 但在非 'use client' 组件中调用 | 若需 onClick 导航,确保组件标记为 Client Component,并导入 useRouter;但优先推荐 |
| router.query 为空或 undefined | 在 App Router 中误用 Pages Router 的 useRouter() 方式获取参数 | App Router 不使用 router.query,改用 params Prop |
? 补充建议
-
静态生成优化:若宠物数据相对稳定,可在 generateStaticParams 中预生成所有 petId,启用 SSG:
export async function generateStaticParams() { const pets = await fetch('https://mockID.mockapi.io/pets').then(r => r.json()); return pets.map((pet: { id: string }) => ({ petId: pet.id })); } - 加载状态友好提示: 默认无加载反馈,可结合 useOptimistic 或骨架屏提升 UX;
- 类型安全:为 params 添加 TypeScript 接口,避免运行时取值错误。
掌握这套模式后,你不仅能解决当前的 404 问题,更能构建可扩展、高性能的 Next.js 动态路由体系——为宠物救助平台提供流畅、可靠的用户导航体验。










