React 路由(一)

653 阅读3分钟

注:大量截图动图。

一 基础路由

1. 路由链接:Nav和NavLink是Nav
  NavLink是Nav的一个特定版本,NavLink可以有高亮的效果,可以设置选中的className.  
 
     <div className="box">
        <div className="left-nav">
          <div className="linkbtn">
            <Link to="/home">home</Link>
          </div>
          <div className="linkbtn">
            <Link to="/about">about</Link>
          </div>
        </div>
      </div>

2.gif

    <div className="box">
        <div className="left-nav">
          <div className="linkbtn">
            <NavLink to="/home">home</NavLink>
          </div>
          <div className="linkbtn">
            <NavLink to="/about">about</NavLink>
          </div>
        </div>
      </div>

1.gif

可以看出 Nav和NavLink都可以改变路由,不同的是Navlink当前锚点有对应的class(默认为active),如果有高亮的展示应该选择NavLink。可以设置选中的className
<NavLink to="/home" className="linkbtn" activeClassName="activeLink"> home </NavLink>

2. 路由注册
      <div class="right-content">
          <Route path="/home" component={Home}></Route>
          <Route path="/about" component={About}></Route>
       </div>

其中path的值和NavLink to属性的值一致,渲染对应的组件。

3.gif

通常我们为了提高效率,减少路由继续匹配,会在外面套一个Switch标签,路由一旦匹配成功就不会继续向下匹配。
    <div className="box">
        <div className="left-nav">
          <NavLink to="/home/person" className="linkbtn" activeClassName="activeLink">
            home
          </NavLink>
          <NavLink to="/about" className="linkbtn">
            about
          </NavLink>
        </div>
        <div class="right-content">
          <Route path="/home" component={Home}></Route>
          <Route path="/about" component={About}></Route>
          <Route path="/home/person" component={Person}></Route>
        </div>
      </div>

此时点击‘/home/person’,路由匹配的规则是先匹配'/home',再继续匹配‘/home/person’,默认是模糊匹配,所以两个都是符合条件的,都会被渲染。 4.gif

    <div class="right-content">
        <Switch>
          <Route path="/home" component={Home}></Route>
          <Route path="/about" component={About}></Route>
          <Route path="/home/person" component={Person}></Route>
        </Switch>
    </div>

此时路由一旦匹配到就不会继续往下,所以只渲染第一个匹配到的组件Home。

5.gif

如果想要精准匹配路由则设置exact属性

  <Switch>
     <Route path="/home" exact="true" component={Home}></Route>
     <Route path="/about" exact="true" component={About}></Route>
     <Route path="/home/person" exact="true" component={Person}></Route>
  </Switch>

此时匹配到的就会是'/home/person',第三个路由,渲染Person组件

6.gif

二 嵌套路由

此时在home组件再嵌套一层路由:

//app.js
 <div className="box">
        <div className="left-nav">
          <NavLink to="/home" className="linkbtn" activeClassName="activeLink">
            home
          </NavLink>
          <NavLink to="/about" className="linkbtn">
            about
          </NavLink>
        </div>
        <div className="right-content">
          <Switch>
            <Route path="/home" component={Home}></Route>
            <Route path="/about" component={About}></Route>
          </Switch>
        </div>
      </div>
      
//Home
 <div>
   <div>
     <NavLink to="/home/person" className="navlink"></NavLink>
     <NavLink to="/home/message" className="navlink"></NavLink>
   </div>
   <div>
     <Switch>
        <Route path="/home/person" component={Person} ></Route>
        <Route path="/home/message" component={Message} ></Route>
     </Switch>
   </div>
</div>

7.gif 特别的,嵌套的路由要加上上一级的路由,比如这里Person组件的路由不能是‘/person’,而是要加上上一级的‘/home’,写成‘/home/person’,且第一级的路由‘/home’不能是精准匹配,否则就到不了第二级。

三 传参

//message.js
state={
    arr:[
      {id:1,name:'xxx1',message:'yyyyyy1'},
      {id:2,name:'xxx2',message:'yyyyyy2'},
      {id:3,name:'xxx3',message:'yyyyyy3'},
    ]
  }
  render() {
    const {arr} = this.state
    return (
      <div>
        我是Message组件
        {
          arr.map(obj=>{
            return <div  key={obj.id} ><Link to="/home/message/list">{obj.name}</Link></div>
          })
        }
        <hr />
        <Route path="/home/message/list" component={List}></Route>
      </div>
      
    );
  }

8.gif

此时我点击message组件里面的路由链接,展示的都是List组件,不同的是这里我想展示我点击对应的数据,此时就要用到传参,传参有几种常见的方法:

(1)params传参

//message 1629257760(1).jpg 路由链接传参‘/value’,路由后面对应‘/:key’,在对应的组件的props.match.params可以获取到对应的参数

 <div>
        我是Message组件
        {
          arr.map(obj=>{
            return <div  key={obj.id} ><Link to={`/home/message/list/${obj.id}/${obj.name}`}>{obj.name}</Link></div>
          })
        }
        <hr />
        <Route path="/home/message/list/:id/:name" component={List}></Route>
      </div>

9.gif

(2)search传参

在路由链接以‘key=value’这种形式传递,注册路由无需处理

1629268715(1).jpg 接收组件可以在props.location.search取得该值 (备注:获取到的search是urlencoded编码字符串,需要借助querystring解析)

10.gif

(3)state传参

该传递方式在地址栏看不到传递的参数,如果不想被看到传递的值,可以选用该方式 路由链接

1629269571(1).jpg 组件接收通过props.location.state获取传递的参数

11.gif

四 push和replace

路由默认是push方式,每一步都会在history里添加一条数据,但是在传参的时候应该使用replace,可以感受一下差别: push 12.gif replace

13.gif

这里只需要在路由链接增加repalce属性就能实现

1629270471(1).jpg

五 总结

(1)路由链接用Link和NavLink,后者可以补充选中的class,有需要这种效果用NavLink,例如上面例子中的home/about,person/message.不用的用Link,例如message组件里的三个不同的链接。 格式为
<NavLink to="/home"activeClassName="xxx">home </NavLink>
<Link to="/home">home </Link>

注册路由用Router
<Route path="/home" component={Home}></Route>
默认为模糊匹配,要精准匹配补充exact属性
多个路由时,外层包Switch标签,提高路由匹配效率

<Switch>
    <Route path="/home" component={Home}></Route>
    <Route path="/about" component={About}></Route>
    <Redirect to="/home"></Redirect>
</Switch>

其中 Redirect是当路由没有匹配到时,会重定向到指定页面 (2)嵌套路由实质是一样的,要使用嵌套路由使用模糊匹配。
(3)传参分为三种方法:

  • 传递params参数
// 路由链接
<Link to={`/home/message/list/${obj.id}/${obj.name}`} replace>{obj.name}</Link>
//路由注册
 <Route path="/home/message/list/:id/:name"  component={List}></Route>
 //路由接收
   const {id,name} = this.props.match.params
  • 传递search参数
// 路由链接
<Link to={`/home/message/list/?id=${obj.id}&name=${obj.name}`} replace>{obj.name}</Link>
//路由注册 无需处理
 <Route path="/home/message/list"  component={List}></Route>
 //路由接收
   import qs from 'querystring'
   const {id,name} =qs.parse(this.props.location.search.slice(1)) 
  • 传递state参数(地址栏看不到传值)
// 路由链接
<Link to={{ pathname:`/home/message/list`,state:{id:obj.id,name:obj.name}}} replace>{obj.name}</Link>
//路由注册 无需处理
 <Route path="/home/message/list"  component={List}></Route>
 //路由接收
 const {id,name} =this.props.location.state||{};

(4)push和replace模式 在路由注册时,默认为push模式,每次点击路由链接都会往history增加一条数据。 replace则是直接取代最后一条数据改为当前点击路由,history数量不变 在路由链接里设置replace属性可以得到