# 路由

React 中可以使用 react-router-dom 来实现前端路由功能。它使用分别暴露暴露出一些组件以供我们使用。

常用的内置路由组件有:

  • <BrowserRouter>

    用 BrowserRouter 标签包裹整个页面,使页面有一个全局的管理路由关系的路由器。并将路由的模式设置为常规路由模式,类似于 Vue 中 history 模式

  • <HashRouter>

    HashRouter 标签和 BrowserRouter 一样,只是路由模式变更为 hash 模式

  • <Route>

    Route 标签是控制路由组件的显示和隐藏,并且可以使用 exact={true} 将路由匹配模式设置为精准匹配,而不是默认的模糊匹配。若该路由下还有子路由,则不能使用精准匹配模式

  • <Redirect>

    Redirect 标签是设置一个默认的重定向路由,我们可以使用它设定默认路由。当所有路由匹配失败时,也会重定向到该路由

  • <Link>

    Link 标签是用于更改地址栏的路径,当我们点击该标签时地址栏的路径就会变成该标签的路径

  • <NavLink>

    NavLink 标签能够设定导航的默认样式,利用 activeClassName="指定样式类" 可以将导航标签的样式设置为指定的类的样式

  • <Switch>

    Switch 标签的功能是将原本路由的全匹配模式改为匹配完即终止,默认当匹配到多个 Route 标签时会将所有的匹配到的路由组件展示,使用 Switch 包裹则当匹配到第一 Route 时即停止往下匹配

例如我们要实现一个页面的路由切换,那你能利用 <Link><Route> 组件将路由组件和跳转标签关联起来。

// index.jsx
// 使用history模式路由
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import {BrowserRouter} from 'react-router-dom'

ReactDOM.render(
	<BrowserRouter>
		<App/>
	</BrowserRouter>,
document.getElementById('root'))
// app.jsx
// 需求:点击标签跳转到about页面,并启用replace模式和精准匹配
// 		设置默认页面为404
//		设置初次匹配到即停止
import React, { Component } from 'react'
import Home from './components/Home'
import About from './components/About'
import DefaultPage from './components/404'
import {NavLink,Route,Redirect,Switch} from 'react-router-dom'

export default class App extends Component {
	render(){
        return (
            <div>
                <ul>
                    <li>
                        <NavLink to="/about" activeClassName="demo" replace={true}>AboutPage</NavLink>
                        <NavLink to="/home" activeClassName="demo">HomePage</NavLink>
                    </li>
                </ul>
                <div>
                    <Switch>
                        <Route path="/about" exact={true}></Route>
                        <Route path="/home"></Route>
                        <Redirect to="/about">
                    </Switch>
                </div>
              </div>
        )
    }
}

# 路由传参

有时候我们想在路由跳转的时候携带一些参数给对应的路由组件,路由组件可以根据传递过来的参数发送网络请求。在 React 当中有总共有三种路由传参的方式,分别是:

  • params 传参
  • search 传参
  • state 传参

# params 传参

params 传参就是利用地址栏里的 params 参数进行参数的传递,例如组件 A 给组件 B 传递两个 params 参数 idname

// A.jsx
import React,{Component} from 'react'
import {Link,Route,Router} from 'react-router-dom'
import B from "./B.jsx"

export default class A extends Component {
    state = {
        id:"001",
        name:"asuhe"
    }
    render(){
        return (
            <div>
                <div>
                    <Link to={`/b/${this.state.id}/${this.state.name}`}>click</Link>
                </div>
                <div>
                    {/* react-router-dom v6版本以下写法 */}
                    {/* <Route path="/b/:id/:name" component={B} /> */}
                    <Routes>
                        <Route path="/b/:id/:name" element={<B></B>} />
                    </Routes>
                </div>
            </div>
        )
    }
}

而在组件 B 中,我们可以在 props 中接收到多个属性对象,传入的 params 参数我们可以在组件 B 的 props 对象中的 match 里的 params 中获取。

// B.jsx
import React,{Component} from "react"
export default class B extends Component {
    render(){
        console.log(this.props)
    }
}

# react-router-dom v5.x

//路由链接(携带参数):
<Link to='/demo/test/tom/18'}>详情</Link> 
//或 <Link to={{ pathname:'/demo/test/tom/18' }}>详情</Link>

//注册路由(声明接收):
<Route path="/demo/test/:name/:age" component={Test}/>
    
//接收参数:
this.props.match.params

# react-router-dom v6.x

//路由链接(携带参数):
<Link to={{ pathname:`/b/child1/${id}/${title}` }}>Child1</Link>
//或 <Link  to={`/b/child1/${id}/${title}`}>Child1</Link> 

//注册路由(声明接收):
<Route path="/b/child1/:id/:title" component={Test}/>

//接收参数:
import { useParams } from "react-router-dom";
const params = useParams();
//params参数 => {id: "01", title: "消息1"}

# search 传参

React 中的 search 传参实际上就是我们传统请求参数中的 query 传参。只是写法稍微有些差异。

// A.jsx
render(){
    return(
        <div>
            <div>
                <Link to={`/b?id=${this.state.id}&$name={this.state.name}`}>点击跳转至组件B</Link>
            </div>
            <div>
                <Router>
                    <Route path="/b" component={B}></Route>
                </Router>
            </div>
        </div>
    )
}

传入的 search 参数我们可以在组件 B 的 props 对象中的 location 里的 search 中获取。

# react-router-dom v5.x

//路由链接(携带参数):
<Link to='/demo/test?name=tom&age=18'}>详情</Link>

//注册路由(无需声明,正常注册即可):
<Route path="/demo/test" component={Test}/>
        
//接收参数:
this.props.location.search

//备注:获取到的search是urlencoded编码字符串(例如: ?id=10&name=zhangsan),需要借助query-string解析参数成对象

# react-router-dom v6.x

//路由链接(携带参数):
 <Link className="nav" to={`/b/child2?age=20&name=zhangsan`}>Child2</Link>

//注册路由(无需声明,正常注册即可):
<Route path="/b/child2" component={Test}/>
        
//接收参数方法1:
import { useLocation } from "react-router-dom";
import qs from "query-string";
const { search } = useLocation();
//search参数 => {age: "20", name: "zhangsan"}

//接收参数方法2:
import { useSearchParams } from "react-router-dom";
const [searchParams, setSearchParams] = useSearchParams();
// console.log( searchParams.get("id")); // 12

//备注:获取到的search是urlencoded编码字符串(例如: ?age=20&name=zhangsan),需要借助query-string解析参数成对象

# state 传参

state 传参就是把 <Link> 里面的 to 属性换成一个对象,再将路径和参数信息填入该对象。

// A.jsx
render(){
    <div>
        <div>
            <Link to={{pathname:"/b",state:{id:this.state.id,name:this.state.name}}}>点击跳转至组件B</Link>
        </div>
        <div>
            <Router>
                <Route path="/b" component={B}></Route>
            </Router>
        </div>
    </div>
    )
}

传入的 state 参数我们可以在组件 B 的 props 对象中的 location 里的 state 中获取。

# react-router-dom v5.x

//路由链接(携带参数):
<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>

//注册路由(无需声明,正常注册即可):
 <Route path="/demo/test" component={Test}/>
    
//接收参数:
this.props.location.state

//备注:刷新也可以保留住参数

# react-router-dom v6.x

//通过Link的state属性传递参数
 <Link
     className="nav"
     to={`/b/child2`}
     state={{ id: 999, name: "i love merlin" }} 
 >
    Child2
</Link>

//注册路由(无需声明,正常注册即可):
<Route path="/b/child2" component={Test}/>
    
//接收参数:
import { useLocation } from "react-router-dom";
const { state } = useLocation();
//state参数 => {id: 999, name: "我是asuhe"}

//备注:刷新也可以保留住参数

# 编程式路由

编程式路由可以允许我们用 javascript 动态生成路由链接

# react-router-dom v5.x

// A.jsx
class A extends Component {
    pushRoute = ()=>{
        this.props.history.push("/b")
    }
    render(){
        return (
            <div>
                <button onClick={this.pushRoute}></button>
                <Route path="/b" component={B}/>
            </div>

        )
    }
}

# react-router-dom v6.x

function A {
    const navigate = useNavigate()
    navigate('b', {
        state: {
            id: item.id,
            content: item.content,
            title: item.title
        }
    })
    return (
    	<div>
            <button onClick={() => navigate(-1)}>back</button>
            <button onClick={() => navigate(1)}>go</button>
        </div>
    )
}

# withRouter

当我想要在非路由组件中使用路由组件中的 pushreplace 等编程式路由的函数时,就可以使用 withRouter 来获取这些函数。 withRouter 作为一个高阶组件,其作用是将一个组件包裹进 Route 里面,然后 react-router 的三个对象 history,、location、match 就会被放进这个组件的 props 属性中。

import React, { Component } from 'react'
import {withRouter} from 'react-router-dom'
class C extends Component {
	back = ()=>{
		this.props.history.goBack()
	}
  	forward =  ()=>{
		this.props.history.goForward()
	}	
	render() {
		return (
			<div >
                <button onClick={this.back}>回退</button>
                <button onClick={this.forward}>前进</button>
			</div>
		)
	}
}
export default withRouter(C)
更新于

请我喝[茶]~( ̄▽ ̄)~*

Asuhe 微信支付

微信支付

Asuhe 支付宝

支付宝

Asuhe 贝宝

贝宝