在这个教程里,咱们会从一个例子React应用开始学习react-router-dom。其中你会学习如何使用Link
、NavLink
等来实现跳转,Switch
和exact
实现排他路由和浏览器路径历史。javascript
也许学习react-router最好的办法就是用react-router-dom v4来写一个多页的react应用。这个react应用会包含登陆、注册、首页、联系人等页面。可是,首先让咱们来看一下react router v4的概念,以及它与v3有什么不一样的地方。html
v4是react router的一次重写,因此和v3有不少不一样的地方。主要有:java
react-router-dom
里。因此,浏览器里使用的时候只须要import react-router-dom
就能够。BrowerRouter
和HashRouter
。他们各自服务于不一样的情景下。详见下文。{props.children}
来处理嵌套的路由。react-router-dom
是react-router中用于浏览器的。react-router
被分为一下几部分:react
react-router
是核心部分。react-router-dom
提供了浏览器使用须要的定制组件。react-router-native
则专门提供了在原生移动应用中须要用到的部分。因此,若是在本例中实现浏览器开发就只须要安装react-router-dom
。git
如上所说,咱们使用react开发web应用,因此只须要安装react-router-dom
。github
npm install react-router-dom --save
BrowserRouter
,这是对Router
接口的实现。使得页面和浏览器的history保持一致。如:window.location
。HashRouter
,和上面的同样,只是使用的是url的hash部分,好比:window.location.hash
。MemoryRouter
,NativeRouter
,处理react native内的路由。StaticRouter
,处理静态路由,和v3同样。在react-router的各类router中,<BrowserRouter>
和<HashRouter>
是能够在浏览器中使用的。若是你使用的是一个非静态的站点、要处理各类不一样的url那么你就须要使用BrowserRouter
。相反的若是你的server只处理静态的url,那么就使用HashRouter
。web
<Route>组件是react router v4里最有用的组件。背后的使用哲学也很简单,不管什么时候你须要在匹配某个路径的时候绘制一个组件,那么就可使用Route
组件。npm
Route
组件可使用以下的属性:api
path
匹配成功以后会绘制这个组件。还有其余的一些属性,能够用来代替component
属性。浏览器
多数的时候是用component
属性就能够知足。可是,某些状况下你不得不使用render
或children
属性。
如:
使用组件:
<Route exact path="/" component={HomePage} />
使用render
属性实现内联绘制:
<Route path="/" render={()=><div>HomePage</div>} />
来看哥更复杂的:
const FadingRoute = ({ component, ...rest }) => ( <Route {...rest} render={(props) => ( <FadeIn> <componnet {...props} /> </FadeIn> )} /> ) <FadingRoute path="/cool" component={Something} />
使用children
:
<ul> <ListItemLink to="/somewhere" /> <LinkItemLink to="/somewhere-else" /> </ul> const ListItemLink = ({to, ...rest}) => ( <Route path={to} children={({math}) => ( <li className={match ? 'active' : ''}> <Link to={to} {...rest} /> </li> )} /> )
更多关于react-router v4如何匹配路径的内容,请移步这里。
一般状况下,咱们都会在路径里添加参数。这样方便在不一样的组件之间传递一些必要的数据。那么咱们如何才能获取到这些传递的参数,并传递给组件中呢?咱们只须要在路径的最后加上/:param
。如:
<Route path="/:param1" component={HomePage} /> const HomePage = ({match}) => ( <div> <h1> parameter => {match.params.param1} </div> );
一旦有路径能够匹配成功,那么就会穿件一个拥有以下属性的对象,并传入绘制的组件里:
path
和当前的widnow.location
的path部分彻底相同的话。Link
是react router v4特有的一个组件。是用来代替上一版的anchor link。使用Link
能够在React应用的不一样页面之间跳转。与unclor会从新加载整个页面不一样,Link
只会从新加载页面里和当前url能够匹配的部分。
Link
组件须要用到to
属性,这个属性的值就是react router要跳转到的地址。如:
import { Link } from 'react-router-dom'; const Nav = () => ( <Link to '/'>Home</Link> );
当被点击的时候,会跳转到路径:/
。
to
属性的值能够是一个字符串,也能够是一个location(pathname, hash, state和search)对象。好比:
<Link to{{ pathname: '/me', search: '?sort=asc', hash: '#hash', state: { fromHome: true } }} />
Link
也可使用replace
属性,若是点击的话,那么history里的当前领会被replace。
NavLink
是Link
的一个子类,在Link组件的基础上增长了绘制组件的样式,好比:
<NavLink to="/me" activeStyle={{SomeStyle}} activeClassName="selected"> My Profile </NavLink>
如今咱们用react router dom来实现第一个demo。
首先,引入必要的组件。好比:Route
和BrowserRouter
。
import { BrowserRouter, Route } from 'react-router-dom';
接下来,咱们建立一些组件和一些Html标签。同时咱们用react router v4里的Link
和NavLink
组件。
const BaseLayout = () => ( <div className="base"> <header> <p>React Router v4 Browser Example</p> <nav> <ul> <li><Link ="/">Home</Link></li> <li><Link ="/about">About</Link></li> <li><Link ="/me">Profile</Link></li> <li><Link ="/login">Login</Link></li> <li><Link ="/register">Register</Link></li> <li><Link ="/contact">Contact</Link></li> </ul> </nav> </header> <div className="container"> <Route path="/" exact component={HomePage} /> <Route path="/about" component={AboutPage} /> <Route path="/contact" component={ContactPage} /> <Route path="/login" component={LoginPage} /> <Route path="/register" component={RegisterPage} /> <Route path="/me" component={ProfilePage} /> </div> <footer> React Router v4 Browser Example (c) 2017 </footer> </div> );
而后咱们来建立须要的组件:
const HomePage = () => <div>This is a Home Page</div> const LoginPage = () => <div>This is a Login Page</div> const RegisterPage = () => <div>This is a Register Page</div> const ProfilePage = () => <div>This is a Profile Page</div> const AboutPage = () => <div>This is a About Page</div> const ContactPage = () => <div>This is a Contact Page</div>
最后,写App
组件。
const App = () => ( <BrowserRouter> <BaseLayout /> </BrowserRouter> ) render(<App />, document.getElementById('root'));
如你所见,react router v4的组件还很是的易用的。
在上例中,咱们在HomePage
组件的路由里使用了属性exact
。
<Route path="/" exact component={HomePage} />
这是由于v4中的路由默认都是非排他的,这一点和v3的实现思路大相径庭。若是没有exact
属性,HomePage
组件和其余的组件就会同事绘制在页面上。
如,当用户点了登陆链接之后,"/"
和"/login"
都知足匹配条件,对应的登陆组件和Home组件就会同时出如今界面上。可是,这不是咱们期待的结果,因此咱们要给"/"
path加上exact
属性。
如今咱们来看看非排他的路由有什么优势。假如咱们有一个子菜单组件须要显示在profile页面出现的时候也出现。咱们能够简单的修改BasicLayout
来实现。
const BaseLayout = () => ( <div className="base"> <header> <p>React Router v4 Browser Example</p> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li> <Link to="/me">Profile</Link> <Route path="/me" component={ProfileMenu} /> </li> {/*略*/} </ul> </nav> </header> </div> );
这样咱们就会看到对应于"/me"
路径的组件都绘制出来了。这就是非排他路由的好处。
排他路由是react router v3的默认实现。只有第一个匹配的路由对应的组件会被绘制。这一点也能够用react router v4的Switch
组件来实现。在Switch
组件中,只有第一个匹配的路由<Route>
或者<Redirect>
会被绘制:
import { Switch, Route } from 'react-router'; <Switch> <Route exact path="/" component={HomePage} /> <Route path="/about" component={AboutPage} /> <Route path="me" component={ProfilePage} /> <Route component={NotFound} /> </Switch>
react router v4中,提供了一个history
对象。这个对象包含了多个api,能够用来操做浏览器历史等。
你也能够在React应用里使用history
对象的方法:
history.push("/my-path") history.replace("/my-path")
用另外的方法能够写成:
<Link to="/my-path" /> <Redirect to="my-path" />
不管什么时候你要重定向到另一个地址的时候,均可以使用Redirect
组件:
<Redirect to {{ pathname: '/register', search: '?utm=something', state: { referrer: someplage.com } }}>
或者,更为简单的:
<Redirect to="register" />
react router v4让开发react应用变得更加的简单。让react应用内的页面跳转更加简单。你只须要声明一个BrowserRouter
或者HashRouter
,而后在它的内部放上一系列的Route
组件,这些主键只要包含path
和component
属性。不管什么时候有了匹配的路由,那么它就会进行非排他的绘制(全部匹配的路由都会绘制)。你也能够把Route
放在Switch
组件里来实现排他的绘制(只有第一个匹配的路由会被绘制)。你能够在路径中传递参数,match
对象会保留这些参数。最后,全部在web中使用的路由组件都包含在react-router-dom
中。只须要引入react-router-dom
就可使用。