Skip to content

Commit

Permalink
doc: add some md files
Browse files Browse the repository at this point in the history
  • Loading branch information
gongph committed Dec 8, 2024
1 parent c708b69 commit 713c82d
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 2 deletions.
3 changes: 1 addition & 2 deletions .vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default defineConfig({
{ text: "安装", link: "/library/installation" },
{ text: "路由", link: "/library/routing" },
{ text: "导航", link: "/library/navigating" },
{ text: "URL 值", link: "/library/url-values" },
{ text: "URL传值", link: "/library/url-values" },
],
},
],
Expand Down Expand Up @@ -176,7 +176,6 @@ export default defineConfig({
],
},
],

socialLinks: [
{ icon: "github", link: "https://github.com/gongph/react-router7-doc" },
],
Expand Down
29 changes: 29 additions & 0 deletions src/library/installation.md
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
# 安装

你可以用 Vite 脚手架工具创建一个项目,并选择 `React` 模板,除此之外你也可以用自己喜欢的工具启动程序。

```sh
npx create-vite@latest
```

接下来从 npm 安装 React Router 依赖:

```sh
npm i react-router
```

最后,在你的应用程序外层渲染一个 `<BrowserRouter>` 组件:

```tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router";
import App from "./app";

const root = document.getElementById("root");

ReactDOM.createRoot(root).render(
<BrowserRouter>
<App />
</BrowserRouter>
);
```
117 changes: 117 additions & 0 deletions src/library/navigating.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# 导航

使用 `<Link>``<NavLink>``useNavigate` 来进行导航。

## NavLink

该组件适用于那些需要渲染激活状态的导航链接。

```tsx
import { NavLink } from "react-router";

export function MyAppNav() {
return (
<nav>
<NavLink to="/" end>
Home
</NavLink>
<NavLink to="/trending" end>
Trending Concerts
</NavLink>
<NavLink to="/concerts">All Concerts</NavLink>
<NavLink to="/account">Account</NavLink>
</nav>
);
}
```

`<NavLink>` 处于激活状态时,它会自动拥有一个 `.active` 类名,以便于使用 CSS 轻松设置样式:

```css
a.active {
color: red;
}
```

它还在 `className`(类名)、`style`(样式)以及 `children`(子元素)上有回调属性,这些回调属性带有活动状态,可用于内联样式设置或条件渲染。

```tsx
// className
<NavLink
to="/messages"
className={({ isActive }) => (isActive ? "text-red-500" : "text-black")}
>
Messages
</NavLink>
```

```tsx
// style
<NavLink
to="/messages"
style={({ isActive }) => ({
color: isActive ? "red" : "black",
})}
>
Messages
</NavLink>
```

```tsx
// children
<NavLink to="/message">
{({ isActive }) => (
<span className={isActive ? "active" : ""}>
{isActive ? "👉" : ""} Tasks
</span>
)}
</NavLink>
```

## Link

不需要激活样式时,可以使用 `<Link>` 组件。

```tsx
import { Link } from "react-router";

export function LoggedOutMessage() {
return (
<p>
您已退出. <Link to="/login">再次登录</Link>
</p>
);
}
```

## useNavigate

这个钩子(hook)允许程序在无需用户交互的情况下将用户导航至新页面。

对于常规导航而言,最好使用 `<Link>``<NavLink>`。它们能提供更好的默认用户体验,比如键盘事件、无障碍标签、“在新窗口中打开”、右键上下文菜单等等。

如果用户长时间停留在页面上,并且你希望他们能够导航到其他页面,那么 `useNavigate` 是一个不错的选择。例如:

- 表单提交完成之后
- 用户长时间没有操作退出系统
- 有时间限制的游戏界面等等场景

```tsx
import { useNavigate } from "react-router";

export function LoginPage() {
let navigate = useNavigate();

return (
<>
<MyHeader />
<MyLoginForm
onSuccess={() => {
navigate("/dashboard");
}}
/>
<MyFooter />
</>
);
}
```
218 changes: 218 additions & 0 deletions src/library/routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# 路由

## 配置路由

路由是通过渲染 `<Routes>``<Route>` 组件来进行配置的,它将 path 和 对应组件关联了起来。

```tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router";
import App from "./app";

const root = document.getElementById("root");

ReactDOM.createRoot(root).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
</Routes>
</BrowserRouter>
);
```

下面是稍微复杂一点的例子:

```tsx
<Routes>
<Route index element={<Home />} />
<Route path="about" element={<About />} />

<Route element={<AuthLayout />}>
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
</Route>

<Route path="concerts">
<Route index element={<ConcertsHome />} />
<Route path=":city" element={<City />} />
<Route path="trending" element={<Trending />} />
</Route>
</Routes>
```

## 嵌套路由

路由可以被嵌套在父路由中。

```tsx
<Routes>
<Route path="dashboard" element={<Dashboard />}>
<Route index element={<Home />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
```

父路由的 path 会自动添加到子路由的 path 中,所以上面的例子中,会创建两个路由 `"/dashboard"``"/dashboard/settings"`

子路由通过父路由组件中的 `<Outlet/>` 渲染。

::: code-group

```tsx [app/dashboard.tsx]
import { Outlet } from "react-router";

export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
{/* 将被渲染成 <Home/> 或 <Settings/> */}
<Outlet />
</div>
);
}
```

:::

## 布局路由

没有 path 的路由看起来会有一定的嵌套关系,但不会在路由上添加额外的路径。

```tsx{2,9}
<Routes>
<Route element={<MarketingLayout />}>
<Route index element={<MarketingHome />} />
<Route path="contact" element={<Contact />} />
</Route>
<Route path="projects">
<Route index element={<ProjectsHome />} />
<Route element={<ProjectsLayout />}>
<Route path=":pid" element={<Project />} />
<Route path=":pid/edit" element={<EditProject />} />
</Route>
</Route>
</Routes>
```

## 索引路由

索引路由会在其父路由组件对应的 `<Outlet/>` 中进行渲染(就像是默认的子路由一样)。它们通过 `index` 属性来进行配置。

```tsx{4,8}
<Routes>
<Route path="/" element={<Root />}>
{/* 访问 “/” 会被渲染到 Outlet 里 */}
<Route index element={<Home />} />
<Route path="dashboard" element={<Dashboard />}>
{/* 访问 "/dashboard" 会被渲染到 Outlet 里 */}
<Route index element={<DashboardHome />} />
<Route path="settings" element={<Settings />} />
</Route>
</Route>
</Routes>
```

请注意,索引路由不能有子路由。如果你期望实现有子路由这种行为,那你可能需要一个[布局路由](#布局路由)

## 路由前缀

一个不带 `element` 属性的 `<Route path>` 会为其子路由添加路径前缀,无须引入父布局。

```tsx{1}
<Route path="projects">
<Route index element={<ProjectsHome />} />
<Route element={<ProjectsLayout />}>
<Route path=":pid" element={<Project />} />
<Route path=":pid/edit" element={<EditProject />} />
</Route>
</Route>
```

## 动态传参

如果路由的 path 包含 `:`,那么它会被视为动态参数,当路由被匹配时,动态参数将被解析并提供给其他路由 API 接口,比如 `useParams`

```tsx
<Route path="teams/:teamId" element={<Team />} />
```

::: code-group

```tsx [app/team.tsx]
import { useParams } from "react-router";

export default function Team() {
let params = useParams();
// params.teamId
}
```

:::

在一个路由中可以有多个动态参数:

```tsx
<Route path="/c/:categoryId/p/:productId" element={<Product />} />
```

## 可选参数

在动态参数后面添加 `?` 可以使其变为可选参数。

```tsx
<Route path=":lang?/categories" element={<Categories />} />
```

也可以在静态字符串后面加上 `?`,使其变为可选参数:

```tsx
<Route path="users/:userId/edit?" component={<User />} />
```

## 通配符

也被称为 `“捕获所有”``*` 路由,如果一个路由模式以 `/*` 结尾,后面的任意字符串都会匹配到,也包括其他的 `/`

```tsx
<Route path="files/*" element={<File />} />
```

```ts
let params = useParams();
// `params["*"]` 将包含 `files/` 之后剩余的URL内容。
let filePath = params["*"];
```

你可以对 `*` 进行解构,只是必须给它赋一个新的名称。一般命名为 `splat`

```ts
let { "*": splat } = useParams();
```

## 导航

使用 `<Link>``<NavLink>` 进行路由之间的跳转。

```tsx
import { NavLink, Link } from "react-router";

function Header() {
return (
<nav>
{/* NavLink 可以很方便的展示激活状态样式 */}
<NavLink to="/" className={({ isActive }) => (isActive ? "active" : "")}>
Home
</NavLink>

<Link to="/concerts/salt-lake-city">Concerts</Link>
</nav>
);
}
```
Loading

0 comments on commit 713c82d

Please sign in to comment.