一、基本使用
首先安装依赖:
npm i react-router-dom
引入实现路由所需的组件,以及页面组件:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Foo from "./Foo";
import Bar from "./Bar";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/foo" element={<Foo />} />
<Route path="/bar" element={<Bar />} />
</Routes>
</BrowserRouter>
);
}
path
:路径element
:要渲染的组件
注意:
BrowserRouter
组件最好放在最顶层所有组件之外,这样能确保内部组件使用 Link 做路由跳转时不出错
二、路由跳转
在跳转路由时,如果路径是/
开头的则是绝对路由,否则为相对路由,即相对于当前 URL进行改变
2.1 Link 组件
Link组件
只能在Router
内部使用,因此使用到Link组件
的组件一定要放在顶层的 Router 之内
import { Link } from "react-router-dom";
<Link to="foo">to foo</Link>;
2.2 NavLink 组件
NavLink组件
和Link组件
的功能是一致的,区别在于可以判断其to属性
是否是当前匹配到的路由NavLink组件
的style
或className
可以接收一个函数,函数接收一个含有isActive
字段的对象为参数,可根据该参数调整样式
import { NavLink } from "react-router-dom";
function Foo() {
return (
<NavLink style={({ isActive }) => ({ color: isActive ? "red" : "#fff" })}>
Click here
</NavLink>
);
}
2.3 编程式跳转
使用useNavigate
钩子函数生成navigate函数
,可以通过 JS 代码完成路由跳转
useNavigate
取代了原先版本中的useHistory
import { useNavigate } from 'react-router-dom';
function Foo(){
const navigate = useNavigate();
return (
// 上一个路径:/a; 当前路径: /a/a1
<div onClick={() => navigate('/b')}>跳转到/b</div>
<div onClick={() => navigate('a11')}>跳转到/a/a1/a11</div>
<div onClick={() => navigate('../a2')}>跳转到/a/a2</div>
<div onClick={() => navigate(-1)}>跳转到/a</div>
)
}
- 可以直接传入要跳转的目标路由(可以使用相对路径,语法和 JS 相同)
- 传入
-1
表示后退
三、动态路由参数
3.1 路径参数
- 在
Route组件
中的path属性
中定义路径参数 - 在组件内通过
useParams
hook 访问路径参数
<BrowserRouter>
<Routes>
<Route path="/foo/:id" element={<Foo />} />
</Routes>
</BrowserRouter>;
import { useParams } from "react-router-dom";
export default function Foo() {
const params = useParams();
return (
<div>
<h1>{params.id}</h1>
</div>
);
}
路径匹配规则
当URL同时匹配到含有路径参数的路径和无参数路径时,有限匹配没有参数的”具体的“(specific)路径。
<Route path="teams/:teamId" element={<Team />} />
<Route path="teams/new" element={<NewTeamForm />} />
如上的两个路径,将会匹配 teams/new
。
路径的正则匹配已被移除。
兼容类组件
在以前版本中,组件的props
会包含一个match对象
,在其中可以取到路径参数。
但在最新的 6.x 版本中,无法从 props 获取参数。
并且,针对类组件的 withRouter
高阶组件已被移除。因此对于类组件来说,使用参数有两种兼容方法:
- 将类组件改写为函数组件
- 自己写一个 HOC 来包裹类组件,用
useParams
获取参数后通过 props 传入原本的类组件
3.2 search 参数
- 查询参数不需要在路由中定义
- 使用
useSearchParams
hook 来访问和修改查询参数。其用法和useState
类似,会返回当前对象和更改它的方法 - 使用
setSearchParams
时,必须传入所有的查询参数,否则会覆盖已有参数
import { useSearchParams } from "react-router-dom";
// 当前路径为 /foo?id=12
function Foo() {
const [searchParams, setSearchParams] = useSearchParams();
console.log(searchParams.get("id")); // 12
setSearchParams({
name: "foo",
}); // /foo?name=foo
return <div>foo</div>;
}
四、嵌套路由
5.1 路由定义
通过嵌套的书写Route组件
实现对嵌套路由的定义。
path
开头为/
的为绝对路径,反之为相对路径。
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/father" element={<Father />}>
<Route path="child" element={<Child />}></Route>
<Route path=":name" element={<Another />}></Route>
</Route>
</Routes>
5.2 在父组件中展示
在父组件中使用Outlet
来显示匹配到的子组件
import { Outlet } from "react-router-dom";
function Father() {
return (
<div>
// ... 自己组件的内容 // 留给子组件Child的出口
<Outlet />
</div>
);
}
5.3 在组件中定义
可以在任何组件中使用 Routes
组件,且组件内的Routes中,路径默认带上当前组件的路径作为前缀。
注意:此时定义父组件的路由时,要在后面加上 }
</StaticRouter>
);
res.write(html);
res.end();
}
http.createServer(requestHandler).listen(3000);