以前学习了第三版的react-router,但是第四版的改动太大了,设计理念和基本用法也不一样了,彻底能够看做另外一个路由插件来学习。react
react-router如今分为两个部分。一个是针对浏览器运行的react-router-dom。一个是针对React Native应用的react-router-native。今天先写一篇针对web环境的笔记。要在浏览器端使用react-router V4,直接安装react-router-dom便可,他会自动下载react-router做为依赖。web
npm i react-router-dom --save
大多数的路由插件都是在应用初始化的时候配置路由规则,react-router第四版以前也是这样:咱们先在js中定义好Router中路径和组件的关联,而后导入应用中。也就是说,对整个应用而言,路由是静态的,写死的。npm
可是第四版,做者对插件作了大幅改动,他们称之为‘动态路由’。此时<Route>就和React的组件同样,可根据须要生成和销毁,可嵌套在其余组件中。而<Route>自己会将其path特性的路径和当前url匹配,若是匹配成功就渲染UI。因此从效用上,<Route>标签和React的视图组件彻底同样,除了多了个路由功能。api
--开始---浏览器
<Route>session
<Route>是React-Router最重要的组件。它有个path特性,若是path和当前url匹配,它会渲染视图,至于渲染什么东西,主要看<Route>中的render方法:react-router
1.component:url匹配时渲染component指定的组件。app
<Route exact path="/" component={Home}/>
2.render:函数,url匹配时返回JSX做渲染。dom
1 <Route exact path={match.url} render={() => ( 2 <h3>Please select a topic.</h3> 3 )}/>
3.chidlren:函数,无论url是否匹配,都返回JSX进行渲染。不匹配时match === null。函数
1 <ul> 2 <ListItemLink to="/somewhere"/> 3 <ListItemLink to="/somewhere-else"/> 4 </ul> 5 6 const ListItemLink = ({ to, ...rest }) => ( 7 <Route path={to} children={({ match }) => ( 8 <li className={match ? 'active' : ''}> 9 <Link to={to} {...rest}/> 10 </li> 11 )}/> 12 )
如上,ListItemLink返回一个<Route>,这个<Route>组件将被渲染成<li>。url匹配的<li>将添加active样式。
而且,这三个方法均可以传入三个route props,他们都携带和当前路由有关的信息:
match:是个对象,带有params、url、isExact、path四个属性.
params(obj):当前url动态路径的参数。
isExact:url是否彻底匹配:
url(string):当前url的匹配部分。
path(string):用于匹配的路径。
history:初学的时候能够先无论它。虽然对外暴露为一个route props。文档提到,‘history’和‘history object’都指向一个叫‘history package’的东西。它是除了React外,ReactRouter另外一个主要依赖。它提供了在不一样环境下在js层管理session history的实现。相关的history术语还有“browser history”、“hash history” 、“memory history”,这些history对象都有一只的典型的属性和方法,详见history.
location:其意义和location.href同样。表示app的当前位置,或将要去往哪(对其赋值)。它是一个对象形式,如:
1 { 2 key: 'ac3df4', // not with HashHistory! 3 pathname: '/somewhere' 4 search: '?some=search-string', 5 hash: '#howdy', 6 state: { 7 [userDefined]: true 8 } 9 }
这个对象将在上面提到的route的三个渲染方法中出现,做为其prop。在withRoute中也出现。
<Router>:V4中全部Router组件都基于这个底层实现
<BrowserRouter>
<HashRouter>
<MemoryRouter>
<NativeRouter>
<StaticRouter>
这几个Router是react-router应用中使用率比较高的,不过目前看最经常使用的是<BrowserRouter>和<HashRouter>。
前面提到,v4以前都采用声明式路由,但v4开始“路由即组件”,路由组件和app的组件更深刻地耦合了,看一个例子:
1 const Nav = ()=>( 2 <Router> 3 <div> 4 <ul> 5 <li><Link to='/home' >Home</Link></li> 6 <li><Link to='/about'>About</Link></li> 7 <li><Link to='/else'>Else</Link></li> 8 </ul> 9 10 <Route path='/home' component={Home} /> 11 <Route path='/about' component={About} /> 12 <Route path='/else' component={Else} /> 13 </div> 14 </Router> 15 ); 16 17 export default Nav;
在v3中,因为路由规则是预先定义好的,因此只要url跳到某个路径,页面就会从新渲染(跳转)。可是v4中Link和Route必须在同一个Router下,Link点击后Router才会响应并渲染。
若是把Link放到一个Nav组件,把Route放到一个Container组件,而后将他们导入App。
App>Nav+Container
点击Nav中的Link,Container中的Route将不会渲染。这个是须要注意的。
另外,Route也能接受动态参数。
<Route path="list/:id"></Route>
<Link to="list/12"></Link>
获取参数值:{ this.props.match.params.id }
<Switch>
React-Router中提供的Switch组件,意义上和一部的switch语句同样,会将第一个匹配的Route渲染出来。
直接使用一组<Route>和将一组<Route>包含在<Switch>中有什么区别呢?
*纯粹是用一组Route,只要path和url匹配,Route就会渲染出来。若是有两个Route的path都匹配url,这两个Route都会被渲染。
*使用<Switch>来包裹一组Route,只有第一个匹配的Route会被渲染。
嵌套:
由上面的例子可知,Router>Link+Route的模式中,Route充当了视图(或者说页面)的角色,子级的Router>Link+Route能够嵌套在一个Route绑定的组件中,从而达到嵌套路由的目的。
不过此时子级路由的Link和Route的路径要写绝对路径。