最近在写的 React 版记账项目应用了路由库 React Router。它是通过管理 URL,实现组件的切换和状态的变化。在项目中用到的一些功能在此做一个学习记录。
安装
在使用 React Router之前得先创建一个 React 应用。
- 安装 create-react-app 并使用它创建一个 React 项目。
yarn global add create-react-app
create-react-app demo-app --template typescript // 若使用 TS 则需安装 TS 依赖
cd demo-app
- 安装 react-router-dom
yarn add react-router-dom
yarn add --dev @types/react-router-dom // 若使用 TS 则需安装 TS 声明文件
基础用法
举个栗子:制作一个导航栏:有2个页面由路由器处理:一个主页,一个用户页面。 当单击不同的 Link,路由器呈现匹配对应的页面。
import React from "react";
import {BrowserRouter as Router,Switch,Route,Link} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/users">Users</Link></li>
</ul>
</nav>
<Switch>
<Route path="/users"><Users/></Route>
<Route path="/"><Home /></Route>
</Switch>
</div>
</Router>
);
}
function Home() {return <h2>Home1</h2>;}
function Users() {return <h2>Users2</h2>;}
Router
Router 组件本身只是一个容器,真正的路由要通过 Route 组件定义
- Router 有两种模式:History 和 Hash
- Hash:所以如果没有后台服务器,就只能用 Hash
- History:如果有后台服务器,配置所有的路径到首页就能用 History 要使用路由器,只需确保将其呈现在元素层次结构的根目录下即可。
Route Matchers
路线匹配器
- 两个路由匹配组件:Switch 和 Route。 当 Switch 被渲染,它会搜索其 children-Route 内容找到一个其 path 值能够与当前的 URL 匹配。当找到这一个对象时,它将渲染该组件。如果没有 Route 匹配项,则Switch 不呈现任何内容(null)。
import React from "react";
import {BrowserRouter as Router,Switch,Route,Link} from "react-router-dom";
export default function App() {
return (
<div>
<Switch>
<Route path="/about"><About /></Route>
<Route path="/about/:id"><Contact /></Route>
<Route path="/contact/:id"><Contact /></Route>
<Route path="/contact"><AllContacts /></Route>
<Route path="/"><Home/></Route>
<Route path="*"><NotFound/></Route>
</Switch>
</div>
);
}
注意!
- path = "/" 的路由将始终匹配 URL 的开头,渲染对应的 Home 组件,因为所有网址以 / 开头。 因此,我们通常将该 Route 放在最后
<Route exact path="/"> // 若不放在最后得加上 exact
- 只要 path="/xxx" 放在了 path="/xxx/:id" 前面, 如果当前 URL 是 /xxx...,那么只能够渲染 /xxx 路由对应组件,其余的则被忽略。就像 /about
// 解决办法:
<Route path="/contact/:id"><Contact /></Route>
<Route path="/contact"><AllContacts /></Route>
-
path="*" 表示若存在与所有 path 不匹配的 Route ,则渲染 NotFound 组件
-
若不想担心由 Route 书写顺序引发的 bug ,建议给每一个 Route 加上 exact
导航
提供了一个 Link 标签创建链接的组件。相当于 a 标签
<Link to="/">Home</Link> // <a href="/">Home</a>
NavLink 是一种特殊类型的 Link
<NavLink to="/detail" activeClassName="selected">React</NavLink>
// <a href="/redetailact" className="selected">React</a>
API
useHistory
- 回退功能
- 跳转到指定页面
举个栗子:
import {useHistory} from "react-router-dom";
const GoBack = () =>{
const history = useHistory();
const onClickBack = () => {history.goBack();};
const onClickPush = () => {history.push("/detail");};
return (
<button onClick={onClickBack}>回退</button>
<button onClick={onClickPush}>跳到 detail 页面</button>
)
}
useParams
- 获取 URL 参数 useParams 返回 URL 参数的键/值对的对象。使用它来访问当前配对的组件
import React from "react";
import {BrowserRouter as Router,Switch,Route,useParams} from "react-router-dom";
function BlogPost() {
let { slug } = useParams();
return <div>Now showing post {slug}</div>;
}
ReactDOM.render(
<Router>
<Switch>
<Route exact path="/"><HomePage /></Route>
<Route path="/blog/:slug"><BlogPost /></Route>
</Switch>
</Router>,
node
);