• 功能:让用户从一个视图(组件)导航到另一个视图(组件)
  • 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
  • 使用React路由简单来说,就是配置路径和组件

路由的使用

1、安装路由

npm i -S react-router-dom

2、相关组件

  1. Router组件:包裹整个应用,一个React应用只需要使用一次

    Router: HashRouter和BrowserRouter

    - HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)

    - BrowserRouter:使用H5的history API实现(localhost3000/first)

  2. Link/NavLink组件:用于指定导航链接(a标签)

    • to属性:会被编译成 a标签的href属性 to='/main' || to='{{pathname='/main'}}'
    • activeClassName属性:指定样式名
    • Link 不会显示按钮的高亮显示, NavLink 来替代它
    • 最终Link会编译成a标签,
  3. Route组件:指定路由展示组件相关信息(组件渲染)

    • path属性:路由规则,这里需要跟Link组件里面to属性的值一致
    • exact属性:严格匹配, 为true是表示严格匹配,为false时为正常匹配。
    • component属性:展示的组件
    • render属性:用于页面组件级别的权限管理

3、使用

步骤一:定义路由模式

  • 主入口index.js中定义路由模式
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import {HashRouter ar Router} from 'react-router-dom'
ReactDom.render(
<Provider store={store}>
<Router>
<App/>
</Router>
<Provider>,
document.getElementById('root')
)

步骤二:组件内渲染路由 + 路由声明式导航

  1. 导入渲染组件
  2. Route路由渲染组件
  3. 使用Link或NavLink组件完成声明式导航的定义
import React, { Component } from 'react'
import { Route, Link } from 'react-router-dom'
<!-- 导入渲染组件 -->
const Home = () => (<div>Home</div>)
const About = () => (<div>About</div>)
const DashBord = () => (<div>DashBord</div>) class App extends Component {
render() {
return (
<>
<ul>
{/* 声明导航*/ }
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="{{pathname:'/dashbord'}}">DashBord</Link></li>
</ul>
{/*
path:可访问的url路径
component:匹配成功的渲染的组件
exact:严格匹配模式
Route组件中匹配成功,渲染会自动在this.props中添加路由导航相关属性方法
*/ }
<Route path="/" exact component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/dashbord" component={DashBord}></Route>
</>
);
}
} export default App;

路由的扩展

1、路由参数

在Route定义渲染组件时给定动态绑定的参数

  1. params:在路由目标页面中

    • 动态路由定义:<Route path='/detail/:id' component={Detail}>
    • 传递:<NavLink to='/detail/2'>
    • 获取:this.props.match.params
  2. query:通过地址栏中的 ?key=value&key=value,
    • 传递:<NavLink to='/detail?name=cc'>
    • 获取:this.props.location.search
    • 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
  3. state:隐式转参,用于数据的收集
    • 传递:<NavLink to='{{pathname:/detail?name=cc,state:{age:20}}}'>
    • 获取:this.props.location.state
    • 作用:埋点---收集数据统计

2、switch组件

  1. 通常情况下, path和component是一一对应的关系.
  2. Switch可以提高路由匹配效率(单一匹配).
  3. 为了更好地匹配规则,轻易不要舍弃。
  4. Redirect:路由从定向,一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
import { Route,Switch } from 'react-router-dom'
<div>
<div>
<ul>
<li>
<Link to="/Guide/ContactUs">ContactUs</Link>
</li>
</ul>
</div>
<Switch>
<Route path="/Guide/ContactUs" component={ ContactUs } ></Route>
<Route path="/Guide/ContactUs" component={ ContactUs } ></Route>
<Redirect from="/" to="/public"></Redirect>
</Switch>
</div>

3、Route组件三种渲染方式

1、component

  1. 参数:对象<Route path='/home' component={home}/>
  • 直接使用组件类--使用最多的方式
  • 缺点:不能把父组件中的数据通过props传递给路由组件中
  1. 参数:函数<Route path='/home' component={()=><home/>} />
  • 使用函数,可以写条件判断,根据条件来渲染不同的组件
  • 可以通过props来完成父组件中的数据向路由渲染组件传递
  • 缺点:每次匹配路由成功都会从新创建组件---效率低下,不建议使用
<Route path='/home' component={()=>{
return <Home count={this.state.count}/>
}}/>

2、render

<Route path="/home" render={props=><Home />} />

  • render方式渲染,使用函数方式
  • 如果匹配相同,则不重新创建,效率高
  • 建议如果组件对象方式渲染(函数方式)推荐使用render
    <Route path='/home' render={()=>{
    if(this.state.count==1){
    return <Home1 count={this.state.count}/>
    }else{
    retutn <Home2/>
    }
    }}/>

3、children

  1. 组件对象方式:必须匹配到path的路由规则才渲染和render与component一样

    <Route path="/about" children={<About />} />
  2. 函数方式:不管是否和path匹配都渲染
    1. match为null表示当前路由规则和path不匹配,如果为对象则匹配成功
    <Route path="/about" children={match=>{
    if(match){
    return <div>children渲染</div>
    }
    }} />

3种渲染区别总结

比较一

  1. component:可以使用组件类渲染或内联式方式渲染
  2. render:只能使用函数
  3. children:使用函数或直接使用组件对象

比较二

  1. component:内联式渲染方式在每次匹配路由成功后都将创建一个新组件
  2. render,children不会,所以用内联式方式建议使用后两者,内联方式渲染组件,推荐用render

比较三

  1. children的值是一个函数时,无论当前地址和path路径匹不匹配,都将会执行children对应的函数,当children的值为一个组件时,当前地址和path不匹配时,路由组件不渲染
  2. children函数方式渲染,会在形参中接受到一个对象,对象中match属性如果当前地址匹配成功返回对象,否则null

4、编程式路由导航

借助this.prosp.history对象上的API对操作路由跳转、前进、后退

  1. this.prosp.history.push()
  2. this.prosp.history.replace()
  3. this.prosp.history.goBack()
  4. this.prosp.history.goForward()
  5. this.prosp.history.go()

注:默认组件中没有this.props.history方法,需要通过withRouter高阶组件(装饰器)来进行包裹,才能得到。

this.props.history.push(path)

this.props.history.push({
pathname:'',
search:'',
state:{}
})

路由监听

在App.jsx组件中可以添加路由监听

constructor(props) {
super(props);
this.props.history.listen(route=>console.log(route))
}

5、withRouter高阶组件

作用:把不是通过路由切换过来的组件中,将react-router 的 history、location、match 三个对象传入props对象上

  • 如果在你想在一般组件使用 路由组件所特有的API 时, 就要借助 withRouter
  • withRouter可以加工一般组件, 让一般组件具备路由组件所特有的API
  • withRouter的返回值是一个新组件
  1. 引入withRouter

    import { withRouter} from 'react-router-dom'
  2. 执行一下withRouter export default withRouter(Cmp)`

import React, { Component } from 'react'
import {withRouter} from 'react-router-dom' class Header extends Component {
// 回退
back = () => {
this.props.history.goBack()
} // 前进
forward = () => {
this.props.history.goForward()
} /// go
go = () => {
this.props.history.go(2)
} render() {
// console.log('一般组件',this.props)
return (
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={this.back}>回退</button>
<button onClick={this.forward}>前进</button>
<button onClick={this.go}>go</button>
</div>
)
}
} export default withRouter(Header)

6、自定义路由

  • 定义一个普通组件可以是类组件也可以是函数式组件
  • 父组件能向子组件传值 props
  • 不管路由规则是否匹配都要显示组件 Route children渲染方式(函数式)
  • 注意点:react中组件是大写字母开头 html也是组件
import React from 'react'
import {withRouter,Route} from 'react-router-dom'
const MyLink = props=>{
const gourl=()=>{
props.history.push(props.to)
}
const Tag=props.tag||'a'
const Active=props['active-class']||'router-active-class'
return (
<Route path={props.to} children={({match})=>{
if(match){
return <Tag style={{color:'red'}} Onclick={gourl}>{props.children}</Tag>
}
return <Tag onClick={gourl}>{props.children}</Tag>
}}>
)
}
export default withRouter(MyLink)

7、多级路由

在有一些功能中,往往请求地址的前缀是相同的,不同的只是后面一部份,此时就可以使用多级路由(路由嵌套)来实现此路由的定义实现。

例: 路由规则如下

admin/index

admin/user

当前组建的请求uri地址(父组件路由uri)
let pathname=this.props.match.path
return(
<Link to=`${pathname}/index`>用户首页</Link>
<Link to=`${pathname}/list`>用户列表</Link>
写在admin组件内,admin组件通过route来进行渲染
<Route path={`${pathname}/index`} component={main}/>
<Route path={`${pathname}/list`} component={index}/>
)

8、重定向与404

  • 重定向 from从哪里来 to重定向到何处去

    <Redirect from="/home" to="/" />

  • 404设置

    <Route component={Notfound} />

默认:匹配规则是从上项下的,一只匹配下去

switch组件:解决一直匹配问题,只要有一个符合;路由规则就停止匹配

<Switch>
<Route exact path='/news' component={index}/>
<Route path='/news/:id' component={Newss}/>
重定向from来源,to跳转的页面
<Redirect exact from='/' to='/news'>
<Route component={notFound}>
</Switch>

React Router 基本原理

React Router依赖于history.js,它是一个独立的第三方js库。可以用来兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。

  • 老浏览器的history: 通过hash来存储在不同状态下的history信息,对应createHashHistory,通过检测location.hash的值的变化,使用location.replace方法来实现url跳转。通过注册监听window对象上的hashChange事件来监听路由的变化,实现历史记录的回退。
  • 高版本浏览器: 利用HTML5里面的history,对应createBrowserHistory, 使用包括pushStatereplaceState方法来进行跳转。通过注册监听window对象上的popstate事件来监听路由的变化,实现历史记录的回退。
  • node环境下: 在内存中进行历史记录的存储,对应createMemoryHistory。直接在内存里pushpop状态。

react之路由的更多相关文章

  1. < react router>: (路由)

    < react router> (路由): 思维导图: Atrial   文件夹下的index.js 文件内容: import React, { Component } from 'rea ...

  2. react动态路由以及获取动态路由

    业务中会遇到点击列表跳转到详情页, 1.在index.js修改我们的跟组件 新建router2的文件 import React from 'react' import { HashRouter as ...

  3. React中路由的基本使用

    现在我们来搞一搞React中的路由吧,别问我为什么这木喜欢用搞这个字,因为它比较深奥. 注意下面我们使用的是React-Router-DOM React中的路由基本使用还是满简单的,零碎的小东西有点多 ...

  4. 【react router路由】<Router> <Siwtch> <Route>标签

    博客 https://www.jianshu.com/p/ed5e56994f13?from=timeline 文档 http://react-guide.github.io/react-router ...

  5. react前置路由守卫

    react中一切皆组件-- 目标:自定义user界面的前置路由守卫,当用户点击要进入user组件时,路由守卫发起判断,如果条件满足则进入,否则跳转至login组件. .入口文件index.js中代码如 ...

  6. React初识整理(四)--React Router(路由)

    官网:https://reacttraining.com/react-router 后端路由:主要做路径和方法的匹配,从而从后台获取相应的数据 前端路由:用于路径和组件的匹配,从而实现组件的切换. 如 ...

  7. react ---- Router路由的使用和页面跳转

    React-Router的中文文档可以参照如下链接: http://react-guide.github.io/react-router-cn/docs/Introduction.html 首先,我们 ...

  8. react的路由权限控制

    在使用路由的时候,有的时候我们的界面只能够在登录之后才可以看的到,这个时候就需要使用路由权限控制了 找了资料发现一个就是我使用的方法,一个是高阶组件. 原谅菜鸟看不太懂不会使用高阶组件………… 首先在 ...

  9. react的路由中的switch和exact的使用

    刚刚接触react不久,发现在项目中的路由配置中会有switch和exact的使用,现总结如下 switch  为了解决route的唯一渲染(仅仅渲染一个路由路径)出现的 <Switch> ...

  10. 链接进入react二级路由,引发的子组件二次挂载

    这个问题很怪,我两个二级路由从链接进入的时候,会挂载两次子组件. 从链接进入,是因为新页面在新标签页打开的. 有子组件是因为公共组件提取 同样的操作,有一些简单的二级路由页面,就不会挂载两次. 讲道理 ...

随机推荐

  1. efcore分表分库原理解析

    ShardingCore ShardingCore 易用.简单.高性能.普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2+的所有版本,支持efcore2+的所有数据 ...

  2. 梦幻西游H5游戏超详细图文架设教程

    前言 想体验经典Q版西游霸服快乐吗?想体验满级VIP的尊贵吗?想体验一招秒杀的爽快吗?各种极品装备.翅膀.宠物通通给你,就在梦幻西游! 本文讲解梦幻西游H5游戏的架设教程,想研究H5游戏如何实现,体验 ...

  3. Serverless 对研发效能的变革和创新

    作者 | 杨皓然(不瞋) 对企业而言,Serverless 架构有着巨大的应用潜力.随着云产品的完善,产品的集成和被集成能力的加强,软件交付流程自动化能力的提高,我们相信在 Serverless 架构 ...

  4. 洛谷4400 BlueMary的旅行(分层图+最大流)

    qwq 首先,我们观察到题目中提到的每天只能乘坐一次航班的限制,很容易想到建分层图,也就是通过枚举天数,然后每天加入一层新的点. (然而我一开始想的却是erf) 考虑从小到大枚举天数,然后每次新建一层 ...

  5. Apache Common-collection 反序列化利用链解析--TransformedMap链

    Apache Common-collection 反序列化利用链解析 TransformedMap链 参考Java反序列化漏洞分析 - ssooking - 博客园 (cnblogs.com) poc ...

  6. java定时任务调度框架

    java定时任务目前主要有三种: Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,但不能在 ...

  7. [Beta]the Agiles Scrum Meeting 2

    会议时间:2020.5.11 20:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 yjy 修复bug将自动评测改为异步HTTP请求 tq 实现查看.删除测试点功能的后端将自动评测改为异 ...

  8. Codeforces Round #573 (Div. 2) D题题解

    一.题目 ​ Tokitsukaze, CSL and Stone Game ​ Tokitsukaze和CSL正在玩一些石头游戏. ​ 一开始,有n堆的石头,第i堆石头数记为 \(a_i\),两人轮 ...

  9. Linux中检查字符串是否为合法IP地址的shell脚本

    #!/bin/bash #判断IP地址是否为有效IP CHKECK_IP () { CHECK_STEP1=`echo $1 | awk -F"." '{print NF}'` i ...

  10. Prometheus重新标记

    Prometheus重新标记 一.背景 二.简化的指标抓取的生命周期 1.配置参数详解 1.`action:`存在的值 1.替换标签值 2.删除指标 3.创建或删除标签 2.删除标签注意事项 3.几个 ...