以前學習了第三版的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的路徑要寫絕對路徑。