React Router升级到4.0后新增了很多api,现在我们仅仅需要使用react-router-dom。
一些核心概念(以下仅仅是我的一些理解,具体请看官网):
path:匹配路径
exact 精准匹配
component匹配组件
render匹配组件中有子路由的时候使用
Link跳转
NavLink导航跳转
Switch 匹配到第一个路由后便不会继续匹配
Redirect 重定向
HashRouter 路径中有#
BrowserRouter 路径中没有#
4.0中匹配默认不是精准匹配,比如现在有两个路径/a /a/ab 匹配/a的时候/a 、/ab均会匹配
- 基本使用
import React from "react";
import { HashRouter, Route, Link, BrowserRouter } from "react-router-dom";
import About from "./About";
import Topics from "./Tipics";
import Main from "./Main";
export default class Home extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<ul>
<li>
<Link to="/Main"> Main</Link>
</li>
<li>
<Link to="/Topics">Topics</Link>
</li>
<li>
<Link to="/About">About</Link>
</li>
</ul>
<hr />
<Route path="/" component={Main} />
<Route path="/Topics" component={Topics} />
<Route path="/About" component={About} />
</div>
</BrowserRouter>
);
}
}
可以看到当点击Topic或者About的时候,Main也被匹配了,因为Main的路径是/,在匹配到/About的时候也被匹配了,解决方法很简单,只需要添加精准匹配。
修改如下代码:
<Route path="/" component={Main} exact/>
上面那种方法将逻辑与路由混合在一起,不便于维护,于是我们可以将router.js单独抽离出来,修改后的代码:
Router.js:
import React from "react";
import { HashRouter, Route, Link, BrowserRouter } from "react-router-dom";
import About from "./About";
import Topics from "./Tipics";
import Main from "./Main";
import Home from "./Home";
export default class IRouter extends React.Component {
render() {
return (
<BrowserRouter>
<Home>
<Route path="/" component={Main} exact />
<Route path="/Topics" component={Topics} />
<Route path="/About" component={About} />
</Home>
</BrowserRouter>
);
}
}
Main.js:
import React from "react";
import { HashRouter, Route, Link, BrowserRouter } from "react-router-dom";
import About from "./About";
import Topics from "./Tipics";
import Main from "./Main";
export default class Home extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<ul>
<li>
<Link to="/Main"> Main</Link>
</li>
<li>
<Link to="/Topics">Topics</Link>
</li>
<li>
<Link to="/About">About</Link>
</li>
</ul>
<hr />
{this.props.children}
</div>
</BrowserRouter>
);
}
}
此时项目目录如下:
仔细看两种方式是一样,都是匹配到组件后加载到children中,第二种方便维护,因此推荐第二种。
综合例子:
import React from "react";
import { Route, BrowserRouter, Switch, Redirect } from "react-router-dom";
import About from "./About";
import Topics from "./Topics";
import Main from "./Main";
import Home from "./Home";
import NoMatch from "./NoMatch";
import Children from "./Children";
export default class IRouter extends React.Component {
render() {
return (
<BrowserRouter>
<Home>
<Switch>
<Route
path="/home"
render={() => (
<Main>
<Route path="/home/children" component={Children} />
</Main>
)}
/>
<Route path="/Topics" component={Topics} />
<Route path="/About" component={About} />
<Redirect path="/" to="/home" exact />
<Route component={NoMatch} />
</Switch>
</Home>
</BrowserRouter>
);
}
}
这个例子包含几个功能:
- 初始路由跳转,即刚开始载入页面的时候时候进行跳转
- 嵌套路由
- noMatch匹配,即输入不存在的路径跳到noMath
效果如下:
总体来说就是结合react-router-rom的不同api使用,为了方便大家查看,我将代码放在了这里