React Router V5 学习记录

react-router 是一个由 meta(facebook) 官方维护的专用于 react 应用的路由组件库。

本文对 v5 版本的 react-router-dom 库基本 api 等和常用知识点进行记录。


基本使用

类似于 Vue Router,React Router 包括两种路由模式:BrowserRouterHashRouter

  • BrowserRouter 模式中,React Router 对 html5 内置的 history 对象进行了封装,路由切换时效果更好;

  • HashRouter 模式中,Router 采用锚点的方式进行页面跳转,对低版本浏览器的兼容更好,但 url 中会多显示一个 /#/

基本使用流程如下:

  1. 在顶层组件中进行全局路由模式的引入。
1
2
3
4
5
6
7
root.render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
);
  1. 使用 Link 组件代替 html 原生的 <a> 标签。
1
2
3
4
5
6
7
8
9
10
11
<nav>
{/*
<a href="#" className="nav-item">Home</a>
*/}
<Link to="/home className="nav-item">
Home
</Link>
<Link to="/about" className="nav-item">
About
</Link>
</nav>
  1. 在需要渲染路由组件的位置使用 Route 组件进行路由的注册
1
2
3
4
<section>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
</section>

即可实现基本的路由功能。

补充:当前的组件还不能支持路由跳转后的高亮显示,可将 Link 组件使用 NavLink 进行代替

NavLink 效用:会默认对当前路由所在的路由链接添加一个 active css 类, 也可使用 activeClassName 属性指定其他的 css 类名。

例:

1
2
3
4
5
6
7
8
<nav>
<NavLink to="/home" activeClassName="active" className="nav-item">
Home
</NavLink>
<NavLink to="/about" activeClassName="active" className="nav-item">
About
</NavLink>
</nav>

进一步优化

路由重定向

访问页面时,页面会自动匹配根路径的资源。若根路径无内容时,可通过 Redirect 组件重定向到想要默认展示的页面。

逻辑上感觉有点类似于 switch case

1
2
3
4
5
<Switch>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
<Redirect to="/home" />
</Switch>

路由模糊匹配和精确匹配

要开启精确匹配,只需在注册路由时添加一个 exact 属性,不过要注意可能会对多级路由的匹配造成负面影响。

1
<Route exact path="/home" component={Home} />

Switch 组件使用

1
2
3
4
5
6
7
<section>
<Route path="/test/home" component={Home} />
<Route path="/test/about" component={About} />
<Route path="/test/about" component={About} />
<Route path="/test/about" component={About} />
<Route path="/test/about" component={About} />
</section>

在上述的例子中,我们会发现,当路由跳转到 /test/about 后,第二个 About 组件和后续所有注册的路由都会渲染在页面上。

为了解决这个问题,可以在路由注册的外层包裹一个 Switch 组件,Switch 组件可在同一 path 匹配成功后就不进行后续重名路由的渲染。

1
2
3
4
5
6
7
8
<section>
{/* 使用 switch 后同个 path 的路由匹配成功后只会挂载第一个 */}
<Switch>
<Route path="/test/home" component={Home} />
<Route path="/test/about" component={About} />
<Route path="/test/about" component={About} />
</Switch>
</section>

其他 api

路由传参

React Router 的路由传参方式有以下三种:

通过 params 方式进行传参

路由注册时,使用类似于后端 restful 路由的方式。

而在Link 组件直接传递相应的 url。

在子组件中,通过 props.match.params 就可获取到相应参数。这种方式较为常用。

1
2
3
<Link to={`/home/message/detail/${id}`}>{title}</Link>

<Route path="/home/message/detail/:id" component={Detail} />

通过 search(类似 ajax 中显式 query)方式进行传参

这种方式只需在路由链接中显式传递 query 参数,而路由注册时无需更改。

在子组件中,通过 props.location.search 就可获取到相应参数,不过获取到的为一个 urlencoded 格式的字符串,需要手动或通过第三方 qs 操作库进行转换。

1
2
3
<Link to={`/home/message/detail/?id=${id}&title=${title}`}>{title}</Link>

<Route path="/home/message/detail" component={Detail} />

通过 state 方式隐式传参

需在路由链接中传递包含 pathnamestate 属性的对象,路由注册时无需更改。

在子组件中,通过 props.location.state 就可获取到相应参数,但要注意,数据全部保存在浏览器 BOM 对象中的 history 属性上,清除缓存后数据会丢失。

可在使用 state 时通过逻辑或为其赋一个空对象,避免页面出错。

1
2
3
4
5
<Link to={{ pathname: "/home/message/detail", state: { id, title } }}>
{title}
</Link>

<Route path="/home/message/detail" component={Detail} />

replace 模式

exact 类似,给路由链接添加一个 replace 属性后即开启 replace 模式,作用就是替换默认的 go 行为,路由跳转会替换当前的历史记录,无法通过后退返回。

1
2
3
4
5
6
7
<Link
// replace 模式,替换当前历史记录
replace
to={{ pathname: "/home/message/detail", state: { id, title } }}
>
{title}
</Link>

函数式编程

根组件在包裹上 Router 组件后,每个路由组件就默认将 historymatchlocation 等三个属性传递进了 props 中,在自定义函数中直接调用就可实现函数式编程。

1
2
3
4
5
6
const handleReplaceBtnClick = (id, title) => {
const { replace } = props.history;
return () => {
replace(`/home/message/detail/${id}/${title}`);
};
};