美文网首页游戏王的故事
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