zoukankan      html  css  js  c++  java
  • 【共享单车】—— React后台管理系统开发手记:Router 4.0路由实战演练

    前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录。最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star。


     一、React Router 4.0核心概念

         4.0版本中已不需要路由配置,一切皆组件

    • react-router:基础路由包
    1. 提供了一些router的核心api,包括Router,Route,Switch等
    • react-router-dom:基于浏览器的路由(包含react-router)
    1. 提供了BrowerRouter,HashRouter,Route,Link,NavLink
    2. 安装:
      npm install react-router-dom --save
      //或
      yarn add react-router-dom  

         react-router-dom核心用法

    • HashRouter和BrowserRouter区别
    1. HashRouter
      http://localhost:3000/#/admin/buttons  
    2. BrowserRouter
      http://localhost:3000/admin/buttons
      
    • Route用法
    1. path属性:路由地址
    2. component属性:路由对应要跳转到的组件
    3. exact属性:代表精准匹配,必须path完全匹配才可以加载对应组件
    4. render方法:渲染一个组件,其中包裹一个子路由
      <Route path="/admin/ui/buttons" component={Button} /> 
      
      <Route path="/admin" render={() => 
      
           <Admin>
                <Route path="/admin/home"  component={Home} />
           </Admin>
      }/>
      
    • 导航
    1. NavLink:菜单里的导航;Link:超链接导航
    2. to:可以传一个字符串,也可以传一个location对象
      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>
      }    
      
      <Link to={{pathname:'/three/7'}}>Three #7</Link> 
    3. 定义:<Route path="/three/:number" /> 

    4. 取值:this.props.match.params.number

    5. 一个基本的location对象: {  pathname: '/',  search:'',  hash:'',  key:'abc123',  state:{} }

    • Switch 选择

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

    2. <Switch>是唯一的因为它仅仅只会渲染一个路径
      <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">

    二、React Router4.0 Demo介绍

    嵌套路由 动态路由

         混合组件化 -- 将Route和Link放到同一个页面 

    • HashRouter将Link和Router进行包裹,其内部必须只能有一个子节点
    • 渲染对应component中的组件
    1. 通过Link组件的to属性设置路由地址
    2. 通过Route组件的path属性匹配路由地址
    • 注意:Route添加exact属性可以做到【路径精准匹配】,否则/about既可以匹配 也可以匹配 /about 等路由地址

         Demo代码

    • 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>
                        <Switch>
                            <Route path="/" exact={true} component={Main}></Route>
                            <Route path="/about" component={About}></Route>
                            <Route path="/topics" component={Topics}></Route>
                        </Switch>
                    </div>   
                </HashRouter>
            );
        }
      }
      export default Home; 

      Main.js :路由组件 (其它组件同Main.js)

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

      index.js:将Home组件挂载到根节点上

      import Home from './pages/router_demo/Home'
      
      ReactDOM.render(<Home />, document.getElementById('root'));

         配置化 -- 将Route路由提取到一个单独的JS文件中 

    • Router、Link和Route
    1. Router是节点 ——下面只能包含一个盒子标签,如这里的div,内容为路由及路由组件
      <Router>
           <div>
              //otherCoding
           </div>
      </Router>  
    2. Link是链接 —— 在html界面中会解析成a标签,to代表链接地址(一个相对路径 ) 
      <Router>
           <div>
              <ul>
                 <li><link to='/'>首页</Link></li>
                 <li><link to='/other'>其他页</Link></li>
              </ul>
           </div>
      </Router>
    3. Route是路由组件 —— path代表路径,component代表路径所对应的界面

      <Router>
            <div>
                <ul>
                    <li><Link to="/home">首页</Link></li>
                    <li><Link to="/other">其他页</Link></li>
                </ul>
                <Route path="/home" component={Home}/>
                <Route path="/other" component={Other}/>
            </div>
      </Router>
      
    • 配置化实现路由功能

    1. router.js:根据Home.js中的Link导航配置找到对应的组件
      import React from 'react'
      import {HashRouter as Router,Route} from 'react-router-dom' 
      import Main from './Main';
      import About from './About';
      import Topics from './Topics';
      import Home from './Home'
      
      export default class IRouter extends React.Component{
      
          render(){
              return (
                  <Router>
                      <Home>
                          {/*根据导航配置找到对应的组件*/}
                          <Route path="/" exact={true} component={Main}></Route>
                          <Route path="/about" component={About}></Route>
                          <Route path="/topics" component={Topics}></Route>
                      </Home>
                  </Router>
              )
          }
      }  
    2. Home.js:①页面中配置Link导航  ②在router.js中通过Route找到组件  ③呈现在{this.props.children}处

      import React from 'react';
      import {Link} from 'react-router-dom'
      
      class Home extends React.Component{
        render(){
            return( 
                    <div>
                        {/*页面导航的配置*/}
                        <ul>
                            <li>
                                <Link to="/">Home</Link>
                            </li>
                            <li>
                                <Link to="/about">About</Link>
                            </li>
                            <li>
                                <Link to="/topics">Topics</Link>
                            </li>
                        </ul>
                        <hr />
                        {/*找到路由匹配的组件后呈现的位置*/}
                        {this.props.children}  
                    </div> 
            );
        }
      }
      export default Home;   
    3. index.js:将router组件挂载到根节点上
      import Router from './pages/router_demo/router'
      
      ReactDOM.render(<Router />, document.getElementById('root'));
      
    • 嵌套路由 

    1. router.js:使用render方法渲染Main主页面极其嵌套路由;注意箭头函数后不能加{},否则只执行,并不会返回(return)

      import User from './User';
      
      {/*改变Main路由,添加render方法*/}
       <Route path="/main" render={() => 
              <Main>
                    <Route path="/main/user" component={User}></Route>
              </Main>
       }></Route>  
    2. Main.js:使用Link配置子路由导航,同时设置子路由显示的位置{this.props.children}

      import {Link} from 'react-router-dom'
      
      {/*添加Link配置子路由导航*/}
      <Link to='/main/user'>嵌套路由</Link>
      <hr />
      {this.props.children}  
    3. 坑:因为前面main组件的路由添加了exact={true}精确匹配,会导致/user不被匹配,无法获取子路由
    4. 解决:去掉exact属性,使用/main匹配main组件路由,/main/user匹配user子组件路由
    • 获取动态路由的值
    1. Main.js:设置跳转的路由链接
      <Link to='/main/test-id'>动态路由1</Link>
      <br />
      <Link to='/main/456'>动态路由2</Link>
    2. router.js:添加动态路由,即path:"/main/:value"用冒号定义的路由内容

      import Info from './Info';
      
      {/*用冒号定义路由内容*/}
      <Route path="/main" render={() => 
           <Main>
                  <Route path="/main/:value" component={Info}></Route>
           </Main>
      }></Route>
    3. 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;
      
    • 匹配路由的404页面

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

      import {HashRouter as Router,Route,Switch} from 'react-router-dom'
      import NoMatch from './NoMatch'
      
      <Switch>
             {/*Switch组件从上到下,只匹配一个路由*/}
             <Route path="/main" render={() => 
                    <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>
    2. NoMatch.js

      import React from 'react';
      class NoMatch extends React.Component{
          render(){
              return(
                  <div>
                      404 Not Found
                  </div>
              );
          }
      }
      export default NoMatch;
      

    三、项目路由实战开发

    • index.js:挂载Router组件到根节点
      // import Admin from './admin'
      import Router from './router'
      
      ReactDOM.render(<Router />, document.getElementById('root'));
      
    • App.js:项目路由入口文件

    1. 用户访问项目时输入url对应的作为整个文件输出,一共有三种情况:登录、详情页、首页
    2. App.js内部什么都没有,只有{this.props.children},主要用来存放子组件(即上述三个页面),否则没有显示位置
      /**路由入口组件 */
      
      import React, { Component } from 'react';
      import './App.css';
      
      class App extends Component {
        render() {
          return (
              <div>
                 {this.props.children}
              </div>
          );
        }
      }
      
      export default App;
      
    3. 总结:想利用Route显示组件信息,则必须有调动{this.props.children}显示其页面的组件

    • src->router.js:有三个页面就需要有三个路由

    1. path为/login渲染登录组件

    2. path为/admin渲染首页:①用render函数返回子路由Admin组件 ②定义嵌套路由/admin/ui/buttons显示组件按钮 ③无path显示404页面 ④外层用Switch包裹保证只显示其中第一个匹配的Route
    3. path为/order/detail渲染详情页

      import React from 'react'
      import {HashRouter, Route, Switch} from 'react-router-dom'
      import App from './App'
      import Login from './pages/Login'
      import NoMatch from './pages/NoMatch'
      import Admin from './admin'
      import Buttons from './pages/ui/buttons'
      
      export default class IRouter extends React.Component{
      
          render() {
              return (
                 <HashRouter>
                     <App>
                        <Route path="/login" component={Login}></Route>
                        <Route path="/admin" render={() => 
                            <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>
              )
          }
      }
    • src->admin.js:content部分使用{this.props.children}显示在router.js中Route得到的页面
      <Row className="content">
           {/* <Home /> */}
           {this.props.children}   
      </Row> 
    • NevLeft->index.js:通过左侧导航栏进行跳转
    1. 有Route就一定要有Link指定路由地址
    2. 利用react-router-dom的NavLink设置路由地址,NavLink组件显示的内容为{item.title},to跳转的地址为{item.key}
      import {NavLink} from 'react-router-dom'
      
      return <Menu.Item title={item.title} key={item.key}>
                       <NavLink to={item.key}>{item.title}</NavLink>
             </Menu.Item>
      
    • pages->ui->button.js:匹配的是/admin/ui/buttons则将Button组件渲染到Admin组件的content中

      import React,{Component} from 'react';
      class Buttons extends Component{
        render(){
            return(
                <div>
                    this is Buttons.
                </div>
            );
        }
      }
      export default Buttons;
    • pages->NoMatch->index.js:没有对应的路由匹配则将404页面渲染到Admin组件的content中

      import React,{Component} from 'react';
      class NoMatch extends Component{
        render(){
            return(
                <div style={{textAlign: 'center', fontSize:'24'}}>
                    404 No Found !!!
                </div>
            );
        }
      }
      export default NoMatch;

    注:项目来自慕课网

  • 相关阅读:
    Redis缓存穿透、缓存雪崩、redis并发问题 并发竞争key的解决方案 (阿里)
    CAP原则 (阿里)
    分布式系统一致性问题解决实战(阿里) 异步解耦+消息队列可作为分布式系统满足最终一致性的优秀方案
    高并发&高可用系统的常见应对策略 秒杀等-(阿里)
    Redis的内存回收策略和内存上限(阿里)
    如何保证MQ的顺序性?比如Kafka
    spring的controller默认是单例还是多例
    HashMap线程不安全的体现
    TCP的三次握手与四次挥手
    常见排序算法及对应的时间复杂度和空间复杂度
  • 原文地址:https://www.cnblogs.com/ljq66/p/10192428.html
Copyright © 2011-2022 走看看