一、問題由來
最近准備上手react,下載了一個react+antd做的后台管理demo玩耍了一下,發現使用的react-router v3,在v4已經發布這么久的前提下繼續玩耍v3是如何也說不過去的,然后就順帶升級了一下,其中踩的一些坑總結一下給各位分享。
二、v3到v4主要有哪些變化?
1.萬物皆組件,所以v4只是一堆提供了導航功能的組件(還有若干對象和方法):
react-router React Router 核心
react-router-dom web使用的版本(本文討論和使用的對象)
react-router-native 用於 React Native 的 React Router
react-router-redux React Router 和 Redux 的集成
react-router-config 靜態路由配置的小助手
2.v3中的router被 BrowserRouter 和 HashRouter 取代,分別取代v4中的 history={browserHistory} 和 history={hashHistory} 代碼如下:
1 //v3寫法 2 import {Router, Route, hashHistory, IndexRedirect} from 'react-router'; 3 <Router history={hashHistory}> 4 <Route ...> 5 </Router> 6 7 8 //v4寫法 9 import {BrowserRouter as Router, Route, Switch} from 'react-router-dom'; 10 <Router> 11 <Switch> 12 <Route exact path='/' component={Login}/> 13 <Route path='/app' component={Layout}/> 14 <Route path='/login' component={Login}/> 15 </Switch> 16 </Router> 17 <Router>
3.v4 中已經沒有 <IndexRoute> 了,但可以使用 <Route exact> 來達到同樣的效果,新增的<Switch>標簽,用於互斥路由;
4.不再通過通過 <Route> 組件的嵌套來實現布局和頁面嵌套,v3中將路由集中在一起處理,即使分離到若干文件中,本質也是一個配置文件;v4中路由規則位於布局和 UI 本身之間,因為route本身也是一個組件,所以我們玩耍的demo中的嵌套router需要重寫了:
1 //v3路由 2 <Router history={hashHistory}> 3 <Route path={'/'} components={Page}> 4 <IndexRedirect to="/app/dashboard/index"/> 5 <Route path={'app'} component={App}> 6 ...... 7 </Route> 8 <Route path={'login'} components={Login}/> 9 <Route path={'404'} component={NotFound}/> 10 </Route> 11 </Router> 12 13 //v4中,我們需要實現嵌套路由本質是將路由以組件的形式分散到需要匹配的地方 14 export default class App extends Component { 15 render() { 16 return ( 17 <div style={{height: '100%'}}> 18 <Router> 19 <Switch> 20 <Route exact path='/' component={Login}/> 21 <Route path='/app' component={Layout}/> 22 <Route path='/login' component={Login}/> 23 </Switch> 24 </Router> 25 </div> 26 ) 27 } 28 } 29 30 class Layout extends React.Component { 31 render() { 32 return ( 33 <Layout> 34 <Sider> 35 <Content style={{margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280}}> 36 <Switch> 37 <Route path="/app/first" component={FirstPage}/> 38 <Route path="/app/second" component={SecondPage}/> 39 </Switch> 40 </Content> 41 </Sider> 42 </Layout> 43 ); 44 } 45 } 46 47 class FirstPage extends React.Component { 48 render() { 49 return ( 50 <div>這是第一個頁面</div> 51 ); 52 } 53 } 54 55 56 class SecondPage extends React.Component { 57 render() { 58 return ( 59 <div>這是第一個頁面</div> 60 ); 61 } 62 }
上面代碼如果暫時看不懂沒關系,我們一步一步拆解,首先App作為根組件初始化,這時候我們有三個路由"/","/app","/login",由於v4路由的包容性路由,凡是"/app/**"的路由將匹配到"/app",例如“/app/first”和“/app/second”都將匹配到“/app”,而exact的作用則是打破包容性路由規則,否則所有“/**”都將匹配到“/”,就沒其他路由啥事兒了。
Layout作為嵌套路由中處理不同布局的子路由,例如我們的demo中,作為管理系統,必然有 login, data-list,data-detail等不同布局的頁面,而data-list和data-detail具有相同的左側菜單欄和Header、Footer。Layout中引入公共的左側菜單欄和Header、Footer,數據頁面都匹配到這里。當然如果展示數據需要多種布局,完全可以Layout1,Layout2......
我們的數據表有用戶表,訂單表,新聞表等等,FirstPage,SecondPage等就是這些具體業務數據的頁面,“/app/first”或者“/app/first”的匹配路徑:App->Layou->FirstPage,至此一個基本的嵌套路由就完成了,其他復雜路由可以同理擴展。
