WinddSnow

React-Router-v6-Part2-Nested-Routes-Navigation-useNavigate-Route-Guards

字数统计: 5.1k阅读时长: 23 min
2026/08/01

第98课:React Router v6(下)——嵌套路由、导航、useNavigate、路由守卫

上一课我们学习了 React Router v6 的路由配置基础——BrowserRouterRoutesRoute 和基本的导航组件。真实的应用远不止简单的“一对一”路径映射:页面通常由共享布局(如侧边栏 + 内容区)组成,不同子页面在布局内切换;用户登录后某些页面才可访问;表单提交后需要编程式跳转;URL 中的查询参数(如搜索关键词、分页)需要方便地读写。React Router v6 为这些场景提供了强大的工具:嵌套路由与 <Outlet> 实现布局复用、**useNavigate** 实现命令式导航、**useSearchParams** 管理查询字符串、以及通过路由守卫模式保护敏感页面。本节课将逐一深入这些进阶能力,并通过一个带认证的仪表板综合示例将它们串联起来。


1. 嵌套路由与共享布局:<Outlet>

1.1 为什么需要嵌套路由?

在典型的后台管理系统中,所有页面共享相同的侧边栏和顶栏,只有主内容区域随路由变化。如果没有嵌套路由,你需要在每个页面组件中手动引入布局组件,或者在路由配置中重复包裹布局——这既繁琐又容易出错。嵌套路由允许你定义一个父路由渲染共享布局,并在布局中预留一个“插槽”(<Outlet>),子路由匹配的内容会自动渲染到该插槽中。

1.2 <Outlet>:子路由的渲染占位符

<Outlet> 是 React Router v6 提供的组件,它标记了子路由内容应该出现的位置。父路由的 element 中渲染 <Outlet />,子路由通过嵌套 <Route> 来定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { BrowserRouter, Routes, Route, Outlet, Link } from 'react-router-dom';

// 共享布局组件
function DashboardLayout() {
return (
<div style={{ display: 'flex' }}>
<aside style={{ width: 200, background: '#f5f5f5', padding: 16 }}>
<nav>
<Link to="/dashboard">概览</Link>
<br />
<Link to="/dashboard/users">用户管理</Link>
<br />
<Link to="/dashboard/settings">设置</Link>
</nav>
</aside>
<main style={{ flex: 1, padding: 16 }}>
{/* 子路由的内容会被渲染在这里 */}
<Outlet />
</main>
</div>
);
}

// 子页面组件
function DashboardHome() {
return <h2>仪表板概览</h2>;
}
function Users() {
return <h2>用户管理</h2>;
}
function Settings() {
return <h2>设置</h2>;
}

function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/dashboard" element={<DashboardLayout />}>
{/* 嵌套子路由:路径相对于父路径 */}
<Route index element={<DashboardHome />} />
<Route path="users" element={<Users />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
</BrowserRouter>
);
}

关键规则

  • 父路由 element 中必须包含 <Outlet />,否则子路由内容不会显示。
  • 子路由的 path相对于父路由路径的。上例中 path="users" 实际匹配 /dashboard/users,不需要写完整路径。
  • index 子路由(不带 path)在父路径精确匹配时渲染(如 /dashboard 精确匹配时渲染 <DashboardHome />)。

1.3 多层嵌套

嵌套可以无限层级。例如,用户管理页面下还可以再嵌套用户详情:

1
2
3
4
5
6
7
8
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="users" element={<UsersLayout />}>
<Route index element={<UserList />} /> {/* /dashboard/users */}
<Route path=":userId" element={<UserDetail />} /> {/* /dashboard/users/:userId */}
</Route>
<Route path="settings" element={<Settings />} />
</Route>

UsersLayout 内部同样渲染 <Outlet />,二级子路由的内容会渲染到该 <Outlet> 中。这种层层嵌套的结构使得 UI 层级与路由层级完全对应,代码组织清晰直观。

1.4 useOutletContext:向子路由传递数据

父路由组件可以向 <Outlet> 传递上下文数据,子路由组件通过 useOutletContext 接收。这避免了将数据通过 URL 参数或状态管理库传递的麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 父组件
function DashboardLayout() {
const [user, setUser] = useState({ name: 'Alice', role: 'admin' });

return (
<div>
<Outlet context={{ user, setUser }} /> {/* 通过 context 传递 */}
</div>
);
}

// 子组件
import { useOutletContext } from 'react-router-dom';

function DashboardHome() {
const { user } = useOutletContext();
return <h2>欢迎,{user.name}!</h2>;
}

2. useNavigate:编程式导航

声明式导航(<Link><NavLink>)适合用户点击链接的场景,但很多情况下你需要通过代码逻辑触发跳转——如表单提交成功后跳转到列表页、登录成功后跳转到主页、或是在异步操作完成后执行重定向。useNavigate 返回一个函数,用于命令式地改变 URL。

2.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { useNavigate } from 'react-router-dom';

function LoginForm() {
const navigate = useNavigate();

async function handleSubmit(e) {
e.preventDefault();
// 假设登录成功
await login();
// 跳转到仪表板
navigate('/dashboard');
}

return (
<form onSubmit={handleSubmit}>
{/* 表单内容 */}
</form>
);
}

navigate(to, options?) 的第一个参数与 <Link to> 相同,可以是字符串或对象。第二个可选参数 options 支持:

  • **replace: boolean**:如果为 true,将替换当前历史记录条目(而非新增一个条目)。适用于登录后跳转(用户按“返回”时不应该回到登录页)。
  • **state: any**:携带任意状态数据,传递给目标路由,可通过 useLocation().state 获取。
  • **relative: 'route' | 'path'**:控制相对路径的解析方式(通常无需设置,默认行为已足够)。
1
2
3
4
5
// 替换当前历史条目,用户无法通过“后退”回到此页
navigate('/dashboard', { replace: true });

// 携带状态
navigate('/checkout', { state: { fromCart: true } });

2.2 数字导航:navigate(-1)

与浏览器的 history.go() 类似,navigate 可以接收一个整数,表示在历史记录栈中前进或后退

1
2
3
<button onClick={() => navigate(-1)}>返回上一页</button>
<button onClick={() => navigate(1)}>前进</button>
<button onClick={() => navigate(-2)}>后退两页</button>

2.3 useNavigation:获取导航状态

useNavigation 返回当前导航状态,包含 { state, location, formData } 等字段。state 可以是 'idle''loading''submitting'。它适用于在数据加载期间显示全局进度条或加载指示器。

1
2
3
4
5
6
7
8
import { useNavigation } from 'react-router-dom';

function GlobalLoadingBar() {
const navigation = useNavigation();
if (navigation.state === 'idle') return null;

return <div className="loading-bar">正在加载...</div>;
}

3. useSearchParams:读写查询参数

查询字符串(?page=2&sort=asc)是前端页面传递筛选、分页、排序等状态的标准方式。React Router v6 提供 useSearchParams,它的 API 与 useState 非常相似——返回一个包含当前查询参数和更新函数的数组。

3.1 读取查询参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { useSearchParams } from 'react-router-dom';

function ProductList() {
const [searchParams, setSearchParams] = useSearchParams();
const page = Number(searchParams.get('page')) || 1;
const sort = searchParams.get('sort') || 'desc';
const keyword = searchParams.get('q') || '';

return (
<div>
<p>当前页:{page},排序:{sort},搜索:{keyword}</p>
</div>
);
}

searchParams 是一个 URLSearchParams 实例,拥有 get(key)getAll(key)has(key)toString() 等方法。它不是普通对象,不能直接解构。

3.2 更新查询参数

setSearchParams 类似 setState,接收一个新的查询参数对象(或函数),并自动更新 URL(不会导致页面重新加载)。React Router 会保持组件树中相关状态的一致性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Pagination() {
const [searchParams, setSearchParams] = useSearchParams();
const currentPage = Number(searchParams.get('page') || 1);

function goToPage(page) {
setSearchParams(prev => {
prev.set('page', String(page));
return prev;
});
}

return (
<div>
<button disabled={currentPage <= 1} onClick={() => goToPage(currentPage - 1)}>
上一页
</button>
<span> {currentPage} </span>
<button onClick={() => goToPage(currentPage + 1)}>下一页</button>
</div>
);
}

注意setSearchParamsuseState 的 setter 一样,支持传入函数来基于前一个值更新。但注意要使用 prev 对象上的方法(setdelete)修改,并返回 prev 自身或一个新的 URLSearchParams

3.3 useLocation:获取完整的路径信息

如果你需要读取当前路径的 pathnamesearch(原始查询字符串)、hash(锚点)或 state(通过 navigate 传递的状态),可以使用 useLocation

1
2
3
4
5
6
7
8
9
10
11
12
13
import { useLocation } from 'react-router-dom';

function CurrentPathInfo() {
const location = useLocation();
return (
<div>
<p>路径:{location.pathname}</p>
<p>查询参数:{location.search}</p>
<p>哈希:{location.hash}</p>
<p>状态:{JSON.stringify(location.state)}</p>
</div>
);
}

location.state 常用于接收导航时通过 navigate('/path', { state: { from: 'login' } }) 携带的上下文数据。


4. 路由守卫:保护需要认证的页面

大多数应用都有认证保护的需求——未登录用户访问 /dashboard 时应被重定向到 /login,登录成功后再回到之前想去的页面。React Router 没有内置的“路由守卫”组件(不像 Vue Router 有 beforeEnter),但可以通过封装一个 <ProtectedRoute> 组件来实现。

4.1 实现 <ProtectedRoute>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Navigate, useLocation } from 'react-router-dom';

function ProtectedRoute({ children }) {
const location = useLocation();

// 假设通过 Context 或其他方式获取当前用户
const { user } = useAuth();

if (!user) {
// 未登录:重定向到登录页,并携带当前页面地址(以便登录后跳回)
return <Navigate to="/login" state={{ from: location }} replace />;
}

return children;
}

关键点

  • <Navigate> 是一个 React Router 组件,渲染它会导致立即重定向(在渲染阶段完成,无需等待副作用)。
  • replace 属性确保重定向替换当前历史记录条目,用户按“后退”时不会回到空白页。
  • state={{ from: location }} 将用户原本想访问的页面地址传递给登录页,登录页在登录成功后可以通过 navigate(location.state?.from?.pathname || '/', { replace: true }) 跳回。

4.2 在路由中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Routes>
<Route path="/" element={<PublicHome />} />
<Route path="/login" element={<LoginPage />} />
<Route
path="/dashboard/*"
element={
<ProtectedRoute>
<DashboardLayout />
</ProtectedRoute>
}
>
<Route index element={<DashboardHome />} />
<Route path="users" element={<Users />} />
</Route>
</Routes>

注意:/dashboard/* 中的 * 确保所有以 /dashboard 开头的子路由都会经过 ProtectedRoute 检查。若未登录,整个 <DashboardLayout> 及其子路由都不会渲染,直接重定向到登录页。

4.3 基于角色的守卫扩展

你可以将 ProtectedRoute 扩展为接收 allowedRoles prop,实现更细粒度的权限控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function ProtectedRoute({ children, allowedRoles }) {
const { user } = useAuth();

if (!user) {
return <Navigate to="/login" replace />;
}

if (allowedRoles && !allowedRoles.includes(user.role)) {
return <Navigate to="/unauthorized" replace />;
}

return children;
}

// 使用
<Route
path="/admin/*"
element={
<ProtectedRoute allowedRoles={['admin']}>
<AdminLayout />
</ProtectedRoute>
}
/>

5. 综合实战:带认证的仪表板应用

下面将嵌套路由、useNavigateuseSearchParamsProtectedRouteuseOutletContext 整合为一个完整的仪表板应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// ---- AuthContext.jsx ----
import { createContext, useContext, useState, useMemo } from 'react';

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const value = useMemo(() => ({ user, setUser }), [user]);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export function useAuth() {
return useContext(AuthContext);
}

// ---- ProtectedRoute.jsx ----
import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from './AuthContext';

export function ProtectedRoute({ children }) {
const { user } = useAuth();
const location = useLocation();

if (!user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
}

// ---- DashboardLayout.jsx ----
import { Outlet, Link, useNavigate } from 'react-router-dom';
import { useAuth } from './AuthContext';

export default function DashboardLayout() {
const { user, setUser } = useAuth();
const navigate = useNavigate();

function handleLogout() {
setUser(null);
navigate('/login', { replace: true });
}

return (
<div style={{ display: 'flex', minHeight: '100vh' }}>
<aside style={{ width: 220, background: '#1e293b', color: '#fff', padding: 16 }}>
<h3>仪表板</h3>
<nav>
<Link to="/dashboard" style={{ color: '#93c5fd', display: 'block', margin: '8px 0' }}>概览</Link>
<Link to="/dashboard/users" style={{ color: '#93c5fd', display: 'block', margin: '8px 0' }}>用户管理</Link>
</nav>
</aside>
<main style={{ flex: 1, padding: 24 }}>
<header style={{ display: 'flex', justifyContent: 'space-between' }}>
<h2>欢迎,{user?.name}</h2>
<button onClick={handleLogout}>退出登录</button>
</header>
<Outlet context={{ user }} />
</main>
</div>
);
}

// ---- LoginPage.jsx ----
import { useState } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from './AuthContext';

export default function LoginPage() {
const [username, setUsername] = useState('');
const { setUser } = useAuth();
const navigate = useNavigate();
const location = useLocation();

function handleLogin(e) {
e.preventDefault();
if (!username.trim()) return;
setUser({ name: username, role: 'admin' });
const from = location.state?.from?.pathname || '/dashboard';
navigate(from, { replace: true });
}

return (
<form onSubmit={handleLogin} style={{ padding: 40 }}>
<h2>登录</h2>
<input value={username} onChange={e => setUsername(e.target.value)} placeholder="用户名" />
<button type="submit">登录</button>
</form>
);
}

// ---- App.jsx ----
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { AuthProvider } from './AuthContext';
import { ProtectedRoute } from './ProtectedRoute';
import DashboardLayout from './DashboardLayout';
import LoginPage from './LoginPage';

function DashboardHome() {
return <h3>仪表板概览</h3>;
}
function Users() {
return <h3>用户管理列表</h3>;
}
function NotFound() {
return <h2>404 - 页面未找到</h2>;
}

export default function App() {
return (
<BrowserRouter>
<AuthProvider>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route
path="/dashboard"
element={
<ProtectedRoute>
<DashboardLayout />
</ProtectedRoute>
}
>
<Route index element={<DashboardHome />} />
<Route path="users" element={<Users />} />
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
</AuthProvider>
</BrowserRouter>
);
}

流程解读

  • 用户访问 /dashboardProtectedRoute 检查 usernull → 重定向到 /login,携带 state.from
  • 用户在登录页输入用户名并提交 → setUser 更新 Context → navigate(from, { replace: true }) 跳回原本想去的页面。
  • DashboardLayout 通过 Outlet 渲染子路由,并通过 useOutletContext 向子组件传递 user 对象。
  • 退出登录时 setUser(null)navigate('/login', { replace: true }) 清除历史栈。

课后练习

一、概念自测(选择题 / 填空题)

  1. (单选) React Router v6 中,哪个组件用于渲染嵌套子路由的内容?
    A. <Children>
    B. <RouteChildren>
    C. <Outlet>
    D. <NestedRoute>

  2. (单选) useNavigate 返回的导航函数不能执行以下哪项操作?
    A. 跳转到指定路径 '/dashboard'
    B. 传递状态对象 { from: '/login' }
    C. 跳转到绝对外部 URL 'https://example.com'
    D. 后退到上一页(navigate(-1))。

  3. (填空) 要读取当前 URL 中的查询参数 ?page=2&sort=desc,应使用 useSearchParams Hook,并通过返回的 searchParams.______('page') 获取特定参数的值。

  4. (多选) 以下关于 <ProtectedRoute> 路由守卫的描述,哪些是正确的?
    A. 它通常使用 <Navigate> 组件实现未认证时的重定向。
    B. 它可以接收 allowedRoles 之类的 props 来实现基于角色的权限控制。
    C. 它是 React Router v6 内置的组件,可直接从 react-router-dom 导入。
    D. 它的实现原理依赖于条件渲染——满足条件时返回 children,否则返回 <Navigate>

二、AI 编程任务:编写面向 AI 的提示词

场景:你需要实现一个购物应用的订单流程,包含以下路由和功能:

  • /products:商品列表页(通过 useSearchParams 支持分页参数 ?page=1 和分类筛选 ?category=electronics)。
  • /cart:购物车页面(受保护路由,未登录用户重定向到 /login)。
  • /checkout:结算页面(受保护路由)。
  • /login:登录页面(登录成功后跳转到登录前尝试访问的页面,或默认跳转到 /products)。
  • /order-confirmation:下单成功后的确认页面(通过 navigate 从结算页跳转,并携带状态 { orderId: 12345 })。
  • 提供一个上下文 AuthContext 管理 user 状态,以及 ProtectedRoute 组件。

任务要求:请写出一段完整的中文提示词,发送给 AI,使其生成完整的 React 路由配置及相关组件代码。提示词中需明确指定嵌套路由、useNavigateuseSearchParams 和路由守卫的使用方式。

三、Agent 模式下的提示词示例

你是一个资深前端开发 Agent。请为一个购物应用创建完整的路由和认证流程。需要创建以下文件:

  1. src/contexts/AuthContext.jsx:使用 createContextuseStateuseMemo 创建 AuthProvideruseAuth Hook,管理 user 状态。
  2. src/components/ProtectedRoute.jsx:接收 children,使用 useAuth 判断登录状态。未登录时返回 <Navigate to="/login" state={{ from: location }} replace />,否则返回 children
  3. src/pages/LoginPage.jsx:使用 useAuthsetUser 登录,使用 useNavigateuseLocation 跳转到 from 路径(若不存在则 /products)。
  4. src/pages/ProductList.jsx:使用 useSearchParams 获取 pagecategory 参数,展示模拟商品列表,渲染分页和分类筛选链接(通过 setSearchParams 更新参数)。
  5. src/pages/Cart.jsxsrc/pages/Checkout.jsxsrc/pages/OrderConfirmation.jsx:分别实现购物车、结算页(提交后 navigate('/order-confirmation', { state: { orderId: Date.now() } }))、确认页(通过 useLocation().state 显示订单 ID)。
  6. src/App.jsx:配置 BrowserRouterAuthProvider,定义所有路由,其中 /cart/checkout 包裹 <ProtectedRoute>。还要配置一个 * 404 页面。
  7. 所有组件添加简洁的 JSDoc 注释。完成后列出所有文件内容。

四、面试真题与参考答案

题目(字节跳动前端面试题):

请解释 React Router v6 中嵌套路由的实现方式,以及 <Outlet> 的作用。如何实现一个路由守卫(Protected Route)来保护需要认证的页面?如果用户在未登录时访问受保护页面,如何让他在登录后自动跳转回之前想去的页面?请结合 NavigateuseLocationuseNavigate 说明。

参考答案

React Router v6 中嵌套路由通过将 <Route> 组件嵌套在父 <Route> 内部来实现。父路由的 element 中渲染 <Outlet />,子路由匹配的内容会自动渲染到该 <Outlet> 位置。这种方式使得布局(如侧边栏、顶栏)可以定义在父路由组件中,而无需在每个子页面重复包裹。

路由守卫通常封装为一个组件,例如 <ProtectedRoute>,它接收 children。内部通过自定义 Hook(如 useAuth)判断用户是否已登录:若已登录,直接返回 children;若未登录,返回 <Navigate to="/login" state={{ from: location }} replace />。其中 location 通过 useLocation 获取,保存了用户原本想访问的路径。登录页在登录成功后通过 useNavigatelocation.state?.from?.pathname 获取目标路径,并执行 navigate(from, { replace: true }),从而实现登录后跳回原始页面。replace: true 确保重定向和登录跳转不会在历史记录中留下多余条目。


课后练习答案

一、概念自测答案

  1. C

    • 解析:<Outlet> 是嵌套路由中子路由内容的渲染占位符。A、B、D 均不是 React Router v6 的 API。
  2. C

    • 解析:useNavigate 只能进行应用内部的导航,不能直接跳转到外部绝对 URL(应使用 window.location.href<a> 标签)。A、B、D 均为 useNavigate 支持的功能。
  3. get

    • 解析:searchParams.get('page') 返回对应参数的值(字符串),如果没有则返回 null
  4. A、B、D

    • 解析:C 错误,ProtectedRoute 不是 React Router v6 内置组件,需要开发者自己封装。A(使用 <Navigate> 重定向)、B(可扩展 allowedRoles)、D(条件渲染模式)均为正确描述。

二、AI 编程任务参考答案(提示词示例)

示例提示词
“请使用 React Router v6 创建一个购物应用的订单流程。要求:

  • AuthContext 管理登录状态,ProtectedRoute 组件包裹受保护路由(/cart/checkout)。
  • LoginPage 登录后使用 navigate(from, { replace: true }) 跳回原页面。
  • ProductList 使用 useSearchParams 读取和更新 pagecategory 参数。
  • Checkout 提交后跳转到 /order-confirmation,携带 state: { orderId }
  • 404 页面处理,所有路由通过 BrowserRouter 配置。
  • 输出所有组件的完整代码。”
CATALOG
  1. 1. 第98课:React Router v6(下)——嵌套路由、导航、useNavigate、路由守卫
    1. 1.1. 1. 嵌套路由与共享布局:<Outlet>
      1. 1.1.1. 1.1 为什么需要嵌套路由?
      2. 1.1.2. 1.2 <Outlet>:子路由的渲染占位符
      3. 1.1.3. 1.3 多层嵌套
      4. 1.1.4. 1.4 useOutletContext:向子路由传递数据
    2. 1.2. 2. useNavigate:编程式导航
      1. 1.2.1. 2.1 基本用法
      2. 1.2.2. 2.2 数字导航:navigate(-1)
      3. 1.2.3. 2.3 useNavigation:获取导航状态
    3. 1.3. 3. useSearchParams:读写查询参数
      1. 1.3.1. 3.1 读取查询参数
      2. 1.3.2. 3.2 更新查询参数
      3. 1.3.3. 3.3 useLocation:获取完整的路径信息
    4. 1.4. 4. 路由守卫:保护需要认证的页面
      1. 1.4.1. 4.1 实现 <ProtectedRoute>
      2. 1.4.2. 4.2 在路由中使用
      3. 1.4.3. 4.3 基于角色的守卫扩展
    5. 1.5. 5. 综合实战:带认证的仪表板应用
    6. 1.6. 课后练习
      1. 1.6.1. 一、概念自测(选择题 / 填空题)
      2. 1.6.2. 二、AI 编程任务:编写面向 AI 的提示词
      3. 1.6.3. 三、Agent 模式下的提示词示例
      4. 1.6.4. 四、面试真题与参考答案
    7. 1.7. 课后练习答案
      1. 1.7.1. 一、概念自测答案
      2. 1.7.2. 二、AI 编程任务参考答案(提示词示例)