为了账号安全,请及时绑定邮箱和手机立即绑定

React-Router v4.0 笔记 96 Lumiance

标签:
React.JS

最近用了几次react-router感觉对其使用还不够熟练,所以看着官方文档复习了一下,顺便做个笔记。

因为webpack懒得搭环境了 所以直接上parcel 0 配置 很好用 但是正式开发我还是喜欢webpack 因为足够灵活

先上demo的 github链接

这是官方文档链接

匹配原理

Route 组件匹配采用从上到下依次匹配,直到最后一个路由或者无可匹配的路由为止。若想只匹配一个路由,请使用Switch组件

基本使用

选择Router:

react-router 提供了五种router供选择,但前端常用到的就三种,具体区别 见文档, 这次选择 BrowserRouter
Router  需要传递history
BrowserRouter   (官方推荐) 使用时需要服务器配合配置,若使用webpack开发需打开historyApiFallback选项
HashRouter   url中有一个#号

开始配置

初始配置

现在有三个页面 home , book 和 book的子页面kongfu,如下

  <li><Link to='/'>home</Link></li>
  <li><Link to='/movie'>movie</Link></li>
  <li><Link to='/movie/kongfu'>kongfu</Link></li>
    
  <Route  path='/' component={Home} />
  <Route  path='/movie' component={Movie} />
  <Route  path='/movie/kongfu' component={KongFu} />

每一个被匹配到的路由均渲染了对应的组件,效果图如下:


webp

step1.gif


若我们想只匹配一个组件怎么办?往下看。

使用Switch组件

修改上面的路由部分代码,添加Switch组件

<Switch>
  <Route  path='/' component={Home} />
  <Route  path='/movie' component={Movie} />
  <Route  path='/movie/kongfu' component={KongFu} /></Switch>

无论跳转到任何一个路由都只会匹配第一个路由home。效果图如下:


webp

step2.gif

但是我们并不想要这样的结果,有两个办法可以解决

  1. 把最精确的路由放在最前面

  2. Route组件添加exact属性

如下

// 第一种方法<Switch>
  <Route  path='/movie/kongfu' component={KongFu} />
  <Route  path='/movie' component={Movie} />
  <Route  path='/' component={Home} /></Switch>// 第二种方法<Switch>
  <Route exact path='/' component={Home} />
  <Route exact  path='/movie' component={Movie} />
  <Route exact path='/movie/kongfu' component={KongFu} /></Switch>

效果图如下:

webp

step3.gif


布局

单个布局

我们日常使用过程中经常会有导航栏或者侧边栏的需求,如下。
header作为导航栏部分, main作为匹配路由的部分

  <header style={{backgroundColor:'#b8cca6'}}>
    <h1>This is header</h1>
  </header>

  <main style={{backgroundColor:'#26899e'}}>
    <Switch>
      <Route exact path='/' component={Home} />
      <Route exact path='/movie' component={Movie} />
      <Route exact path='/book' component={Book} />
    </Switch>
  </main>

为了效果,明显对header以及main部分加了背景色,如下图:

webp

step4.gif


如果我们有多个布局怎么办? 比如常见的还有登录布局,往下看。

多个布局

为实现多个布局我们将多个布局提取成多个组件

/***** BasicLayout.jsx *****/<div>
  <h1>BasicLayout!!</h1>
    <Route exact path='/' component={Home} />
    <Route exact path='/movie' component={Movie} />
    <Route exact path='/book' component={Book} /></div>  /***** LoginLayout.jsx *****/<div>
  <h1>LoginLayout!!</h1>
  <form action="">
    username: <input type="text" placeholder='please input username'/>
    <br />
    password: <input type="password" placeholder='please input password'/>
  </form></div>/***** App.jsx *****/
// 注意 有子路由的Route不要加exact不然会匹配不到子路由,<Switch>
  <Route path='/login' component={LoginLayout} />
  <Route path='/' component={BasicLayout} /></Switch>

如下图:

webp

step5.gif


登录验证

既然有登录布局 自然就需要有登录验证

官方推荐的做法是自己实现一个AuthRoute,如下

const AuthRoute = (props) => {  const { component:Component, ...rest } = props;  // parcel 默认不支持rest参数, 需添加babel-plugin-transform-object-rest-spread 并添加到.babelrc文件中
  // const rest = {};
  // for (const _key in props) {
  //   if(_key !== 'component') {
  //     rest[_key] = props[_key]
  //   }
  // }

  return (<Route
    {...rest}
    render={(props) => (
      islogin()?
      (<Component {...props} />)
      :
      (<Redirect to='/login' />)
    )}
  />)
}

此处有两个小坑,

  1. parcel默认不支持rest参数,具体看上面代码注释。

  2. Route组件的 component 和 render 都会在路径匹配时渲染组件,但component优先级较高,若两个属性同时出现render会被忽略。

下面看下效果:
首先是未登录状态 任何路由都无法进入 只能停留在login页

webp

step6.gif

下面是登陆后的效果,任何路由都可以访问,登出后之能访问login页


webp

step7.gif

编程式导航

既然有了登录验证 那我们总不能让用户自己点其他路由跳转到首页吧! 下面就来使用withRouter 在登陆成功后让代码手动跳转到首页

const { history } = this.props 
history.push('/');

被Route包裹的组件都会在props拥有history,match,location对象,使用hisory对象的push方法即可进行手动跳转。
效果如下图:


webp

step8.gif

withRouter

若在Route组件之外想要访问 history,match,location对象并做一些操作呢?
这时候withRouter就排上用场了,
每次路由发生变化时Router包裹的组件会被重新渲染,
withRouter包裹的组件就可访问到路由信息对象,就可以响应路由变化

我们改造一下导航部分 将其封装成一个Nav组件, 在export时用withRouter包裹。

import { withRouter, Link } from 'react-router-dom';

class Nav extends Component {
  render() {
    const activeStyle = {
      backgroundColor: '#00a74a'
    }
    const path = this.props.location.pathname;
    console.log('test', this.props)
    return (      <ul>
        <li><Link to='/login' style={path === '/login'?activeStyle:{}} >login</Link ></li>
        <li><Link to='/' style={path === '/'?activeStyle:{}} >home</Link ></li>
        <li><Link to='/movie' style={path === '/movie'?activeStyle:{}}>movie</Link ></li>
        <li><Link to='/book' style={path === '/book'?activeStyle:{}}>book</Link ></li>
      </ul>
    )
  }
}

export default withRouter(Nav);

效果如下图:

webp

step9.gif

以上就是一些react-router v4的一些基本使用。若有错误欢迎指出!

Tips: 注意看文中的Route 和Router 就差一个字母 不要看花了眼哦



作者:Lumiance
链接:https://www.jianshu.com/p/bb05ac984dab


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消