美文网首页游戏王的故事
React:Router基本使用

React:Router基本使用

作者: SwiftBirds | 来源:发表于2019-09-25 08:01 被阅读0次

    版本区别

    react-router 4之后的版本和之前的版本差别真的很大

    嵌套路由

    v3中的嵌套路由通常书写如下,路由集中写在一起

    import { Router, Route, IndexRoute } from 'react-router'
    
    const PrimaryLayout = props => (
      <div className="primary-layout">
        <header>
          Our React Router 3 App
        </header>
        <main>
          {props.children}
        </main>
      </div>
    )
    
    const HomePage =() => <div>Home Page</div>
    const UsersPage = () => <div>Users Page</div>
    
    const App = () => (
      <Router history={browserHistory}>
        <Route path="/" component={PrimaryLayout}>
          <IndexRoute component={HomePage} />
          <Route path="/users" component={UsersPage} />
        </Route>
      </Router>
    )
    
    render(<App />, document.getElementById('root'))
    

    以下是v3中的一些关键概念,这些概念在v4中不再适用:

    • 路由器集中在一个地方。
    • 布局和页面嵌套是通过嵌套<Route>组件派生的。
    • 布局和页面组件完全天真,因为它们是路由器的一部分。

    React Router 4不再提倡集中式路由器。相反,路由规则存在于布局内以及UI本身之间。这里是v4中的相同应用程序:

    import { BrowserRouter, Route } from 'react-router-dom'
    
    const PrimaryLayout = () => (
      <div className="primary-layout">
        <header>
          Our React Router 4 App
        </header>
        <main>
          <Route path="/" exact component={HomePage} />
          <Route path="/users" component={UsersPage} />
        </main>
      </div>
    )
    
    const HomePage =() => <div>Home Page</div>
    const UsersPage = () => <div>Users Page</div>
    
    const App = () => (
      <BrowserRouter>
        <PrimaryLayout />
      </BrowserRouter>
    )
    
    render(<App />, document.getElementById('root'))
    

    exact

    v4以后的版本,路由匹配默任情况下,在匹配到了符合条件的路由后,并不会停止匹配,而是会继续匹配符合条件的路由。
    exact是Route的一个属性,认为其是一种严格匹配模式

    • 当exact为false时,根据路由匹配所有组件,如"/" 匹配 “/”、“/home”、“/home/menu,“/home”则会匹配“/”、“/home/menu;
    • 当exact为true时,则“/” 仅匹配“/”、无法匹配到“/home”。
    <Route path='/' component={Home} />
    <Route path='/page' component={Page}>
    //这种情况下,如果匹配路由path='/page',那么会把Home也会展示出来。
    //既路由path='/page'会匹配路由path='/'和路由path='/page'
    
    <Route exact path='/' component={Home} />
    <Route path='/page' component={Page} />
    //这样匹配路由path='/page',只会匹配到Page组件
    

    该属性主要解决父路由和子路由之间的问题。

    Switch

    如果只需要一个满足匹配要求的组件,则使用<Switch>路由,它会在匹配到第一个适合的卢友初停住。

    <Switch>
        <Route path="/" exact component={HomePage} />
        <Route path="/users/add" component={UserAddPage} />
        <Route path="/users" component={UsersPage} />
        <Redirect to="/" />
    </Switch>
    

    上例在输入"/users"或者"/users/add"时,最终都会只渲染{UserAddPage}。如果在给"/users/add"添加exact,则输入"/users"只会匹配"/users","/users/add"只会匹配"/users/add"。

    Redirect

    如果没有解析路由,则使用<Switch>和<Redirect>重定向到具有有效路径的默认页面,甚至是未找到的页面(自己定义的404页面)。<Redirect>一般放在最后面。

    例如在下例中,如果<Redirect>之上的路由全部没有匹配到,则会重定向到定义的NotFound页面。

    <Switch>
        <Route path='/login' component={Login} />
        <Route path='/register' component={Register} />
        <Route path="/order/detail/:orderId" component={OrderMap} /> 
        <Route path="/admin" component={Admin} />
        <Route path="/error" component={NotFound}/>
        <Redirect to="/error" />
    </Switch>
    

    以下写法能实现与上例相同的效果,优点是在<Switch>中不用定义NotFound页面的路由。缺点是在其它地方需要跳转到NotFound页面时,还是需要再次定义NotFound的路由。

    <Switch>
        <Route path='/login' component={Login} />
        <Route path='/register' component={Register} />
        <Route path="/order/detail/:orderId" component={OrderMap} /> 
        <Route path="/admin" component={Admin} />
        <Route component={NotFound}/> 
    </Switch>
    

    withRouter

    如果一个组件没有被<Route>包裹,则它无法使用this.props.history.push进行路由的跳转。withRouter的作用就是将一个组件包裹进Route里面, 然后react-router的三个对象history, location, match就会被放进这个组件的props属性中.

    // withRouter实现原理: 
    // 将组件包裹进 Route, 然后返回
    const withRouter = () => {
        return () => {
            return <Route component={Nav} />
        }
    }
    
    // 这里是简化版
    const withRouter = ( Component ) => () => <Route component={ Component }/>
    

    实际项目中,直接使用修饰器@withRouter写在class之前,如下所示。

    @withRouter
    class AuthRouter extends Component {
        // code
    }
    

    实际体验

    业务需求

    设置一个登陆界面、注册界面、用户界面的路由。在用户界面,导航栏和头部、尾部的组件是通用的,内容组件需要设置路由来达到切换。其它路由重定向到404界面。

    登录.PNG 用户界面.PNG

    代码分析

    主要用到了嵌套路由、Switch和Redirect。在index界面的路由设置如下,首先通过<AuthRouter>组件判断用户登录信息,不满足登录情况,则会通过this.props.history.push()跳转到Login页面;满足登录条件则会去<Switch>里面匹配路由,若未匹配到路由,则重定向到404页面。

    <div>
        <BrowserRouter>
            <AuthRouter></AuthRouter>
            <Switch>
                <Route path='/login' component={Login} />
                <Route path='/register' component={Register} />
                <Route path="/order/detail/:orderId" component={OrderMap} /> 
                <Route path="/admin" component={Admin} />
                {/* <Route component={NotFound}/> */}
                <Route path="/error" component={NotFound}/>
                <Redirect to="/error" />
            </Switch>
        </BrowserRouter> 
    </div> 
    

    若匹配到了admin页面,则会进入到<Admin>组件中去继续匹配对应的子组件,匹配过程与上面相似,<Admin>组件的渲染代码如下

    <Row className='container'>
        <Col span='4' className='navi-left'>
            <NaviLeft />
        </Col>
        <Col span='20' className='main'>
            <Header className='header' history={this.props.history}/>
            <Row className='content'> 
                <Switch>
                    <Route path='/admin/home'  component={Home} />
                    <Route path='/admin/city'  component={City} />
                    <Route path='/admin/order'  component={Order} />
                    <Route path='/admin/user'  component={User} />
                    <Route path='/admin/Map'  component={bikeMap} />
                    <Route path='/admin/charts/bar'  component={Bar} />
                    <Route path='/admin/charts/line'  component={Line} />
                    <Route path='/admin/charts/pie'  component={Pie} />
                    <Route path='/admin/permission'  component={Permission} />
                    <Route component={NotFound}/>
                    {/* <Redirect to="/error"></Redirect> */}
                </Switch>   
            </Row>
            <Footer className='footer'/>
        </Col>
    </Row>
    

    相关文章

      网友评论

        本文标题:React:Router基本使用

        本文链接:https://www.haomeiwen.com/subject/ukhluctx.html