前端
一点也不简单

React中的router(路由)

现在常用的有两个版本3.X和4.X的

  • 3.X:react-router
  • 4.X:react-router-dom

我们以4.X的版本为例

路由的模式

HashRouter

老浏览器提供的 hash模式, 我们称之为: HashRouter

import { HashRouter as Router } from 'react-router-dom'    //hash路由

BrowserRouter

H5提供的的 hsitory 模式,我们称之为 BrowserRouter

import { BrowserRouter as Router} from 'react-router-dom'     //history路由

设置在主入口文件index.js里

路由的使用

我们需要用前面的路由模式里的Router包裹主入口文件index.js里的App组件

ReactDOM.render(
          <Router>
              <App />
          </Router>, 
            document.getElementById('root')
          );

一级路由

一级路由书写在App.js里

先安装依赖react-router-dom,生产环境安装(建议在更前面的安装)

npm i react-router-dom -S

我们需要引入一些路由经常用到的模块

import { Route,Link,NavLink,Redirect,Switch,withRouter } from 'react-router-dom'

书写路由展示区域Route

<Route  exact path = "/" render = { () => (<Redirect to = '/home'></Redirect>) }></Route>
<Route  path = "/home" component = { Home }></Route>
<Route  path = "/mine" component = { Mine }></Route>
<Route  path = "/list" component = { List }></Route>

第一个是重定向,将/匹配到的路由重定向到/home,因为我们希望初次打开的/页面就能在/home,所以我们需要重定向

exact是路由完全匹配如果不使用exact的话可以理解为是一个以/**模式的模糊匹配效果,只要是以/打头的路由都会被匹配到,倘若这里不加exact会报错:

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

所以在这里应当加上exact!!!!!

建立对应的组件

这些组件我们还没有,需要去建立并且引入

~~~~~建立组件引入中~~~~每个组件以这样的形式存在

import React,{ Component,Fragment } from 'react'

class List extends Component {
    render () {
        return (
            <Fragment>
                List
            </Fragment>
        )
    }
}

export default List

组件也建立好了,但是我们没有跳转按钮,这个时候我们本应该写跳转按钮,但是路由是否有效我们不清楚,那就在地址栏手动更改地址看看是否可以

路由测试

重定向和路由都正常。

增加导航按钮

现在书写导航按钮

<a href="/home">Home</a>
<a href="/list">List</a>

可以没问题,但是vue里我们都有router-link来代替,那么react里有什么???

Link和NavLink

这两个还是有一定区别的

  • Link: 不可以使用路由激活
  • NavLink: 可以使用路由激活(activeClassName)

推荐使用NavLink

写好active样式红底白字,作为路由激活后的样子

<NavLink activeClassName="active" to="/home" className="nav-link">Home</NavLink>
<NavLink activeClassName="active" to="/list" className="nav-link">List</NavLink>
<NavLink activeClassName="active" to="/mine" className="nav-link">Mine</NavLink>
路由激活

一级路由好了。

二级路由

二级路由出现在对应的组件里,以Mine组件为例,一般我的都会有一个登陆一个注册

import React, { Component,Fragment } from 'react';

import Login from './Login.js'
import Register from './Register'

import { NavLink,Route } from 'react-router-dom';

class Mine extends Component {
  render () {
    return (
      <Fragment>
        Mine
        
        {/* 二级路由连接 */}
        <ul className="nav justify-content-center">
            <li className="nav-item">
                <NavLink to = '/mine/login' className="nav-link"> 登录 </NavLink>
            </li>
            <li className="nav-item">
                <NavLink to = "/mine/register" className="nav-link"> 注册 </NavLink>
            </li>
        </ul>

        {/* 二级路由展示区域 */}
        <Route path = "/mine/login" component = { Login }></Route>
        <Route path = "/mine/register" component = { Register }></Route>
      </Fragment>
    )
  }
}

export default Mine

再在当前目录下建立两个组件,Login.js,和Register.js作为登陆和注册(自己定我还是那样建立的)

二级路由

一个简单的二级路由就完成了

路由的编程式导航

  • push
  • replace
  • goBack

这里的编程式导航有个坑,如果不把编程式导航写在方法里,会直接执行

以list组件为例,编程式导航一般可作为返回按钮

我们发现路由组件里都有history这个属性打印一下props.history

class List extends Component {
    render () {
        console.log(this.props.history)
        return (
            <Fragment>
                List

                <button>跳转首页push</button>
                <button>跳转首页replace</button>
                <button>返回</button>
            </Fragment>
        )
    }
}
this.props.history

我么可以发现有了许多的方法

goBack

class List extends Component {
    render () {
        console.log(this.props.history)
        let { goBack } = this.props.history
        return (
            <Fragment>
                List

                <button>跳转首页push</button>
                <button>跳转首页replace</button>
                <button onClick={ goBack }>返回</button>
            </Fragment>
        )
    }
}

发现相当于浏览器顶部栏的回退功能,并且通过这个方法完成的回退可以被浏览器记录

push,replace

class List extends Component {
    render () {
        console.log(this.props.history)
        let { goBack,push } = this.props.history
        return (
            <Fragment>
                List

                <button onClick={push('/home')}>跳转首页push</button>
                <button>跳转首页replace</button>
                <button onClick={ goBack }>返回</button>
            </Fragment>
        )
    }
}

这种写法发现在我进入list页面时会直接跳到home页面,所以换个写法(正确写法)

import React,{ Component,Fragment } from 'react'

class List extends Component {
    goHome = () => {
        this.props.history.push('/home')
      }
    
      homeGo = () => {
        this.props.history.replace('/home')
      }
    render () {
        console.log(this.props.history)
        let { goBack,push } = this.props.history
        return (
            <Fragment>
                List

                <button onClick = { this.goHome }> 跳转首页push </button>
                <button onClick = { this.homeGo }> 跳转首页replace </button>
                <button onClick={ goBack }>返回</button>
            </Fragment>
        )
    }
}

export default List

但是push和replace还是有不同的!!!

push和replace的区别

  • push(我们推荐使用push)

push的跳转操作会被浏览器记录

  • replace

replace的操作不会被浏览器记录

当然仍旧是需要按需选择的

路由的传参接参

传参

<NavLink activeClassName="active" to={{pathname:"/category",search:'?a=1b=2'}} className="nav-link">Category</NavLink>

接参

传递过来的参数会挂载在this.props.location上

import React, { Component,Fragment } from 'react';
class Category extends Component {
  render () {
    // 凡是使用了 Route组件包裹的组件 , 我们称之为 路由组件 
    // 路由组件身上会具备 几个 属性  分别为  histroy  localhost  match
    console.log( this.props )
    return (
      <Fragment>
        Category
        <p> pathname: { this.props.location.pathname } </p>
        <p> search: { this.props.location.search } </p>
        <p> state: { this.props.location.state.count  } </p>
      </Fragment>
    )
  }
}
export default Category

赞(2) 打赏
未经允许不得转载:专注前端开发和vps技术交流的博客-纸飞机 » React中的router(路由)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

微信扫一扫打赏