浅入浅出 react-router v4 实现嵌套路由

一、问题由来

  最近准备上手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,至此一个基本的嵌套路由就完成了,其他复杂路由可以同理扩展。

 

  点我下载嵌套路由demo

 

posted @ 2017-11-12 22:38  Fengly0503  阅读(7690)  评论(1编辑  收藏  举报