React Router4.0

https://reacttraining.com/react-router/web/guides/quick-start

提供 React Router4.0 路由的练习


1.React Router4.0 基本概念介绍
4.0版本已不需要路由配置,一切皆组件

react-router:基础路由包

提供了一些router的核心api,包括Router,Route,Switch等
react-router-dom:基于浏览器端的路由(包含react-router)

提供了BrowserRouter,HashRouter,Route,Link,NavLink
安装:npm install react-router-dom --save或yarn add react-router-dom
react-router-dom核心用法

HashRouter和BrowserRouter

HashRouter的写法eg.http://localhost:3000/#/admin/buttons
BrowserRouter的写法eg.http://localhost:3000/admin/buttons
Route:path、exact、component、render
exact属性代表精准匹配,必须path完全匹配才可以加载对应组件 
eg1.
<Route path='/admin/ui/buttons' component={Buttons}/>
eg2.
<Route path='/admin' render={()=>
    <Admin>
        <Route path='/admin/home' component={Home} />
    </Admin>
}/>
1
2
3
4
5
6
7
8
NavLink应用于菜单里作为菜单导航、Link超链接导航

eg1.
import {Link} from 'react-router-dom';
const Header=()=>{
    <header>
        <nav>
            <li><Link to='/'>Home</Link></li>
            <li><Link to='/about'>About</Link></li>
            <li><Link to='/three'>Three</Link></li>
        </nav>
    </header>
}
eg2.
<Link to={{pathname:'/three/7'}}>Three #7</Link>

定义:<Route path="/three/:number"/>取值:this.props.match.params.number

同时在to属性中可以传递一个location对象,如:

{pathname:'/',search:' ',hash:'',key:'abc123',state:{}}
1
可以通过this.props.match.params.对象属性名取值

Switch[选择符合要求的Route,自上至下找到一个可以匹配的内容则不继续加载其他]

<Switch>
    <Route path='/admin/ui/buttons' component={Buttons}/>
    <Route path='/admin/ui/models' component={Models}/>
    <Route path='/admin/ui/loading' component={Loading}/>
</Switch>

Redirect

路由重定向:<Redirect to="/admin/home">


2.React Router4.0 Demo介绍
4.0基本路由功能DEMO实现-混合组件化【将Route和Link放到同一个页面】

HashRouter将Link和Router进行包裹,其内部必须只能有一个子节点

通过Link组件的to属性设置路由地址;通过Route组件的path属性匹配路由地址,从而渲染对应component中的组件【注意:Route添加exact属性可以做到路径的精准匹配,否则/about既可以匹配/也可以匹配/about等路由地址】

实例代码:

Home.js用于显示整个页面内容

import React from 'react';
import {HashRouter,Route,Link,Switch} from 'react-router-dom'
import Main from './Main';
import About from './About';
import Topics from './Topics';
class Home extends React.Component{
  render(){
      return(
          <HashRouter>
              <div>
                  <ul>
                      <li>
                          <Link to="/">Home</Link>
                      </li>
                      <li>
                          <Link to="/about">About</Link>
                      </li>
                      <li>
                          <Link to="/topics">Topics</Link>
                      </li>
                  </ul>
                  <hr></hr>
                  <Route path="/" exact={true} component={Main}></Route>
                  <Route path="/about" component={About}></Route>
                  <Route path="/topics" component={Topics}></Route>
              </div>   
          </HashRouter>
      );
  }
}
export default Home;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Main.js组件

import React,{Component} from 'react';
class Main extends Component{
  render(){
      return(
          <div>
              this is Main.
          </div>
      );
  }
}
export default Main;
1
2
3
4
5
6
7
8
9
10
11
Topic.js组件

import React,{Component} from 'react';
class Topics extends Component{
  render(){
      return(
          <div>
              this is Topics.
          </div>
      );
  }
}
export default Topics;
1
2
3
4
5
6
7
8
9
10
11
About.js组件

import React,{Component} from 'react';
class About extends Component{
  render(){
      return(
          <div>
              this is About.
          </div>
      );
  }
}
export default About;


4.0基本路由功能DEMO实现-配置化【将Route路由提取到一个单独的JS文件中】

配置化实现路由功能

创建Home.js内部写上ul->li->Link导航组件,并在想要显示对应路由内容的区域写上{this.props.children}即会加载调用Home.js组建时内部传递的信息
创建router.js,最外层用HashRouter包裹,第二级用Home组件包裹,内部写对应路由Route(path路由路径匹配、及component属性渲染的组件)
执行流程,index.js渲染Router组件时,由于最外层是HashRouter,内部是Home组件故加载Home组件内容,并通过{this.props.children}得到在调用Home组件时内部的信息。
嵌套路由

如想实现在Main组件中的嵌套路由,需要在Main组件中添加{this.props.children}从而渲染对应的内部信息,还需要添加Link组件以进行跳转
之后在router.js中对应调用该组件的Route组件中,删除component属性,添加render属性进行页面渲染,render属性内应是一个函数,返回Main组件(内部带有Route属性以进行路由渲染)
注意点: 
调用Main组件的Route不能添加exact属性,因为如果添加exact属性,当点击内部组件路由到对应url时由于与外部Route的path不是完全匹配,故将不会显示
调用Main组件的Route内部render函数如果添加()=>{}则需要在函数体内写return,因为{}表示函数体,内部的函数将被执行,返回组件需要写return;如果不添加大括号则直接写返回的组件即可,ES6箭头函数默认箭头后面的内容是return的
调用Main组件的Route内部Main里的Route组件的path需要包含外部Route的path作为一级路由,如外部是/main内部需要是/main/xxx,如果不以外部Route作为一级路由则不会走外部的Route到内部Route内容
实例代码

/src/pages/router-demo/router2/router.js
import React from 'react';
import {HashRouter as Router,Route,Link}from 'react-router-dom';
import Main from './../router1/Main';
import About from './../router1/About';
import Topics from './../router1/Topics';
import Home from './Home';
class IRoute extends React.Component{
  render(){
      return(
          <Router>
              <Home>
                  <Route path="/main" render={()=>{
                      return(
                      <Main>
                          <Route path="/main/a" component={About}></Route>
                      </Main>
                      );}}></Route>
                  <Route path="/about" component={About}></Route>
                  <Route path="/topics" component={Topics}></Route>
              </Home>
          </Router>
      );
  }
}
export default IRoute;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/src/pages/router-demo/router2/Home.js
import React from 'react';
import {Link} from 'react-router-dom'

class Home extends React.Component{
  render(){
      return(
          <div>
              <ul>
                  <li>
                      <Link to="/main">Home1</Link>
                  </li>
                  <li>
                      <Link to="/about">About1</Link>
                  </li>
                  <li>
                      <Link to="/topics">Topics1</Link>
                  </li>
              </ul>
              <hr></hr>
              {this.props.children}
          </div>
      );
  }
}
export default Home;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/src/pages/router-demo/router2/Main.js
import React,{Component} from 'react';
import {Link} from 'react-router-dom';
class Main extends Component{
  render(){
      return(
          <div>
              this is Main.
              <Link to="/main/a">To start a</Link>
              <hr></hr>
              {this.props.children}
          </div>
      );
  }
}
export default Main;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
获取动态路由的值

在Main.js中设置跳转的路由链接
import React,{Component} from 'react';
import {Link} from 'react-router-dom';
class Main extends Component{
    render(){
        return(
            <div>
                this is Main.<br/>
                <Link to="/main/test-id">嵌套路由1</Link><br/>
                <Link to="/main/456">嵌套路由2</Link>
                <hr></hr>
                {this.props.children}
            </div>
        );
    }
}
export default Main;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在router.js中添加动态路由即path:"/main/:value"用冒号定义的路由内容
import React from 'react';
import {HashRouter as Router,Route,Link,Switch}from 'react-router-dom';
import Main from './Main';
import About from './../router1/About';
import Topics from './../router1/Topics';
import Home from './Home';
import Info from './Info';
import NoMatch from './NoMatch';
class IRoute extends React.Component{
    render(){
        return(
            <Router>
                <Home>
                    <Switch>
                        <Route path="/main" render={()=>{
                            return(
                            <Main>
                                <Route path="/main/:value" component={Info}></Route>
                            </Main>
                            );}}></Route>
                        <Route path="/about" component={About}></Route>
                        <Route path="/topics" component={Topics}></Route>
                        <Route component={NoMatch}></Route>
                    </Switch>
                </Home>
            </Router>
        );
    }
}
export default IRoute;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
在Info.js中获取定义的动态路由内容信息,通过{this.props.match.params.路由的名称}
import React,{Component} from 'react';
class Info extends Component{
    render(){
        return(
            <div>
                这里是测试动态路由功能
                动态路由的值是{this.props.match.params.value}
            </div>
        );
    }
}
export default Info;
1
2
3
4
5
6
7
8
9
10
11
12
添加默认路由

添加react-router-dom的Switch组件包裹Route组件用于设置自上自下只匹配一个路由

添加没有path属性的Route组件放置Switch组件内部的最后位置,作为默认路由

router.js如上代码,NoMatch.js如下所示:

import React from 'react';
class NoMatch extends React.Component{
    render(){
        return(
            <div>
                404 Not Found
            </div>
        );
    }
}
export default NoMatch;
1
2
3
4
5
6
7
8
9
10
11
3.项目路由实战开发
由于用户访问项目时输入url需要有对应的输出,而作为整个文件输出时,一共有三种情况:登录、详情页、首页。故需要编写项目的入口文件router.js并在index.js中引入。【代码省略…】

router文件中定义使用路由的方式为HashRouter(即#/xxx/xxx的形式)

由于我们要访问完整路由时有登录页面、详情页面和首页,router文件需要定义根组件App,App.js内部什么都没有只有{this.props.children},主要用来存放子组件(即上述三个页面)。【如果没有用App进行包裹,即没有地方设置{this.props.children}显示路由的页面内容,即上述三个页面没法显示】

【总结结论:想利用Route显示组件信息,则必须有调动{this.props.children}显示其页面的组件】

有三个页面就需要有三个路由path分别为/login渲染登录组件、/admin渲染首页(其中里用render函数返回子路由Admin组件,并定义嵌套路由/admin/ui/buttons显示组件按钮;无path显示404页面,外层用Switch包裹保证只显示其中第一个匹配的Route)、和/order/detail渲染详情页。

//[/src/router.js]
import React,{Component} from 'react';
import {HashRouter,Route,Switch} from 'react-router-dom';
import App from './App';
import Login from './pages/login';
import Admin from './admin';
import Buttons from './pages/ui/buttons';
import NoMatch from './pages/nomatch';
class IRouter extends Component{
  render(){
      return(
          <HashRouter>
              <App>
                  <Route path="/login" component={Login}></Route>
                  <Route path="/admin" render={()=>{
                      return(
                          <Admin>
                              <Switch>
                                  <Route path="/admin/ui/buttons" component={Buttons}></Route>
                                  <Route component={NoMatch}></Route>
                              </Switch>
                          </Admin>
                      );
                  }}></Route>
                  <Route path="/order/detail" component={Login}></Route>
              </App>
          </HashRouter>
      );
  }
}
export default IRouter;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
将Admin组件中的content部分使用{this.props.children}显示在router.js中Route得到的页面

//[/src/admin.js]
import React from 'react';
import { Row, Col } from 'antd';
import Header from './components/Header';
import Footer from './components/Footer';
import NavLeft from './components/NavLeft';
import Home from './pages/home';
import './style/common.less'
class Admin extends React.Component{
  render(){
      return(
          <Row className="container">
              <Col span={6} className="nav-left">
                  <NavLeft/>
              </Col>
              <Col span={18} className="main">
                  <Header/>
                  <Row className="content">
                      {/* <Home></Home> */}
                      {this.props.children}
                  </Row>
                  <Footer/>
              </Col>
          </Row>
      );
  }
}
export default Admin;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
有Route就一定要有Link指定路由地址,我们在首页中通过左侧导航栏进行跳转,故需要在NavLeft组件中利用react-router-dom的NavLink设置路由地址,NavLink组件显示的内容为{item.title},to跳转的地址为{item.key}

//[/src/components/NavLeft/index.js]
import React from 'react';
import {Menu,Icon} from 'antd';
import MenuConfig from './../../config/menuConfig';
import './index.less';
import MenuItem from 'antd/lib/menu/MenuItem';
import {NavLink} from 'react-router-dom';
const SubMenu = Menu.SubMenu;
class NavLeft extends React.Component{
  componentWillMount(){
      const menuTreeNode = this.renderMenu(MenuConfig);
      this.setState({
          menuTreeNode
      })
  }
  //菜单渲染
  renderMenu=(data)=>{
      return data.map((item,index)=>{
          if(item.children){
              return(
                  <SubMenu title={item.title} key={item.key}>
                      {this.renderMenu(item.children)}
                  </SubMenu>
              )
          }
          return <Menu.Item title={item.title} key={item.key}>
              <NavLink to={item.key}>{item.title}</NavLink>
          </Menu.Item>
      })
  }
  render(){
      return(
          <div>
              <div className="logo">
                  <img src="/assets/logo-ant.svg"  alt=""></img>
                  <h1>Imooc MS</h1>
              </div>
              <Menu theme="dark">
                  {this.state.menuTreeNode}
              </Menu>
          </div>
      );
  }
}  
export default NavLeft;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
在router.js中可以看到如果匹配的是/admin/ui/buttons则将Button组件渲染到Admin组件的content中;如没有写对应的路由匹配则将404页面渲染到Admin组件的content中,对应代码如下

//[/src/pages/ui/buttons.js]
import React,{Component} from 'react';
class Buttons extends Component{
  render(){
      return(
          <div>
              This is Buttons Page.
          </div>
      )
  }
}
export default Buttons;
//[/src/pages/nomatch/index.js]
import React from 'react';
class NoMatch extends React.Component{
  render(){
      return(
          <div style={{textAlign:'center',fontSize:'24'}}>
              404 Not Found!!!
          </div>
      );
  }
}
export default NoMatch;
--------------------- 
作者:汪喆_Jack 
来源:CSDN 
原文:https://blog.csdn.net/qq_34829447/article/details/81916545 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值