深入路由与页面构建
本节课我们将一起实现“GitHub 统计”页面,并应用动态路由、布局、加载 UI 和错误处理等核心知识点。我们将以 github.com/yangjh-xbmu/Web-develop
仓库作为数据来源。
教学目标:
- 在导航栏添加“GitHub 统计”链接。
- 创建
/github-stats
页面,显示提交列表(例如提交信息和作者)。 - 为
/github-stats
创建嵌套布局。 - 实现动态路由
/github-stats/commits/[commitId]
以显示单次提交的详细信息(如提交日期和变更的文件)。 - 为
/github-stats
路由段添加加载状态 UI (loading.js
)。 - 为
/github-stats
路由段添加错误处理 UI (error.js
)。
步骤 1: 修改导航栏并创建基础的 GitHub 统计页面
首先,我们需要在导航栏中添加一个指向新页面的链接。
-
修改导航栏组件 ( Navbar.js )
在
Navbar.js
中添加一个新的链接:- 讲解点 :我们使用了 Next.js 的
<Link>
组件进行客户端导航,这比传统的<a>
标签性能更好。
- 讲解点 :我们使用了 Next.js 的
-
创建 GitHub 统计页面 (
page.js
)在
src/app
目录下创建一个新的文件夹github-stats
,然后在其中创建page.js
文件。- 讲解点 :Next.js 的 App Router 使用基于文件夹的路由系统。
src/app/github-stats/page.js
文件会自动映射到/github-stats
路径。
- 讲解点 :Next.js 的 App Router 使用基于文件夹的路由系统。
现在,运行 npm run dev
,应该能在导航栏看到“GitHub 统计”链接,点击后会显示这个基本页面。
步骤 2: 为 GitHub 统计创建嵌套布局 ( layout.js )
我们可以为 /github-stats 路径下的所有页面创建一个共享的布局。这个布局会嵌套在根布局 layout.js
内部。
-
创建嵌套布局文件
在 src/app/github-stats 目录下创建 layout.js 文件:
- 讲解点 :
- layout.js 文件用于定义共享 UI。此布局将应用于 /github-stats 及其所有子路由。
- 它会自动接收 children props,代表该布局包裹的页面或子布局。
- 根布局
layout.js
中的 Navbar 和 Footer 依然会显示,因为这个布局是嵌套在根布局内的。
- 讲解点 :
步骤 3: 获取并显示提交列表 (服务器组件数据获取)
现在我们来修改 src/app/github-stats/page.js ,使其从 GitHub API 获取提交数据并展示。
- 讲解点 :
- 服务器组件 (Server Components) : GitHubStatsPage 现在是一个 async 函数。这意味着它是一个服务器组件,可以在服务器上直接执行数据获取 ( getCommits )。
- 数据获取 : 使用 fetch API 从 GitHub 获取数据。
- 错误处理 (初步) : try…catch 块用于捕获 getCommits 中可能发生的错误。如果获取失败,我们会显示一个错误消息。更完善的错误处理将通过 error.js 实现。
- 链接到动态路由 :
<Link href={ /github-stats/commits/${commit.sha} }>
为每个提交创建了一个指向其详细页面的链接, commit.sha 将作为动态参数。 - API 速率限制 : GitHub API 对未认证请求有速率限制。
步骤 4: 实现动态路由显示提交详情
现在我们创建动态路由页面,用于显示单个提交的详细信息。
-
创建动态路由文件夹和页面文件
在 src/app/github-stats 目录下创建 commits 文件夹,然后在 commits 文件夹内创建 [commitId] 文件夹 (方括号表示动态段),最后在 [commitId] 文件夹内创建 page.js 。 完整路径: src/app/github-stats/commits/[commitId]/page.js
-
编写动态路由页面组件
- 讲解点 :
- 动态路由参数 : CommitDetailPage 组件通过 params prop 接收动态路由参数。 params.commitId 对应于 URL 中的 [commitId] 段。
- 数据获取 : 同样使用 async/await 和 fetch 获取特定提交的详细信息。
- generateMetadata : (可选) 展示了如何为动态页面生成元数据 (如页面标题),这对于 SEO 很有用。
步骤 5: 实现加载状态 UI ( loading.js )
当数据获取需要时间时,我们可以显示一个加载指示器。
-
创建 loading.js 文件
在 src/app/github-stats 目录下创建 loading.js 文件:
- 讲解点 :
- loading.js 文件导出的组件会在其所在路由段(这里是 /github-stats 及其子路由)的内容加载完成前显示。
- Next.js 会自动将 loading.js 包裹在 React Suspense 边界内。
- 您可以为更细粒度的动态路由(如 src/app/github-stats/commits/[commitId]/loading.js )创建特定的加载 UI,如果该页面的数据加载也比较耗时。 为了明显看到加载效果,您可以在 getCommits 或 getCommitDetails 函数中人为增加延迟: await new Promise(resolve => setTimeout(resolve, 2000)); // 模拟2秒延迟
- 讲解点 :
步骤 6: 实现错误处理 UI ( error.js )
如果数据获取失败或组件渲染时发生错误,我们可以显示一个友好的错误页面。
-
创建 error.js 文件
在 src/app/github-stats 目录下创建 error.js 文件:
-
讲解点 :
-
‘use client’ : 错误组件必须是客户端组件。
-
Props : 错误组件接收两个 props:
- error : 一个 JavaScript Error 对象。
- reset : 一个函数,调用它可以尝试重新渲染产生错误的路由段。
-
错误记录 : useEffect 可以用来将错误信息发送到日志服务。
-
用户体验 : 提供一个“再试一次”的按钮,让用户有机会从临时性错误中恢复。 要测试 error.js ,您可以:
-
在 getCommits 或 getCommitDetails 中故意 throw new Error(‘Simulated fetch error’);
-
或者修改 API URL 为一个无效的地址。
-
总结与回顾
通过这个“GitHub 统计”功能的实现,我们学习并实践了:
- 动态路由 ( [commitId]/page.js ) : 如何根据 URL 参数动态生成页面内容。
- 布局组件 ( layout.js ) : 如何为特定路由段创建共享 UI 结构,并理解嵌套布局的概念。
- 加载状态 UI ( loading.js ) : 如何使用 Suspense 和 loading.js 提升数据加载时的用户体验。
- 错误处理 ( error.js ) : 如何创建错误边界,优雅地处理运行时错误并提供恢复机制。
- 服务器组件数据获取 : 如何在服务器组件中直接使用 async/await 获取外部数据。