版本

v3和v4有一些差距:

https://blog.csdn.net/qq_35484341/article/details/80500237

以下的总结,都是基于V4的

官方文档:https://reacttraining.com/react-router/web/guides/quick-start

核心组件和用法

<BrowserRouter/>
<HashRouter/>
<Route/>
<Switch/>
<Redirect/>
<Link/> (<NavLink/>)
withRouter

不多解释,先上实例:

<BrowserRouter>
<Link to="/">主页</Link>
<Link to="/recommend">推荐</Link>
<Link to="/detail/1">详情</Link> <Route path="/" exact component={Home}/>
<Route path="/detail/:id" exact component={Detail}/>
<Route path="/recommend" exact component={Recomm}/>
</BrowserRouter>

BrowserRouter和HashRouter

这两者可以理解为路由的作用域,所有的Link组件和Route组件都必须在其内部。

浏览器路由和哈希路由的区别:

  • BrowserRouter中的URL指向真实的url,当页面刷新(或直接操作url并回车)时,将产生指向该路径的url请求,如果服务器端没有配置该路径,则返回404。在项目上线后,需要我们去配置服务端。(通过Link并不会向后端发送真实请求)
  • HashRouter中#后面的uri并不是真实的请求路径,对于后端来说,全都指向同一个地址。另外哈希历史记录不支持loaction.key和loaction.state,当通过state传递参数的时候,无法从历史记录中获取到,可能会导致页面显示异常。

在BrowserRouter模式下,如何在服务端配置呢?

  • Nginx配置(前端项目打包),将任何URL访问都指向index.html
  • 后端服务配置(前端项目打包),将任何URL访问都指向index.html
  • 开启前端服务(需要进行Nginx反向代理)

Link

被渲染成a标签,跟href属性的所用类似。点击Link标签和a标签,看到的效果是一样的,但我们推荐<Link>,使用它才是单页面应用,浏览器不会请求页面;而使用a标签,会重新请求页面。

<Link to='/path' />
<Link to={
pathname, // 路径,即 to 的字符串用法
search, // search
hash, // hash
state, // state 对象
action, // location 类型,在点击 Link 时为 PUSH,浏览器前进后退时为 POP,调用
replaceState 方法时为 REPLACE
key, // 用于操作 sessionStorage 存取 state 对象
} />
<Link to='/path' replace={true} /> // 覆盖当前路径

NavLink

Link的加强版

  • activeClassName(string):设置选中样式,默认样式名为active
  • activeStyle(object):当元素被选中时,为此元素添加样式
  • exact(bool):为true时,只有当导致和完全匹配class和style才会应用
  • strict(bool):为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线
  • isActive(func):判断链接是否激活的额外逻辑的功能。可以做导航守卫

Route

具体的路由规则

属性:

// 渲染目标
component // 渲染组件
render
children // 地址匹配
path
<Route path="/hello/:name">
name为参数名,可以在其渲染组件中获取 this.props.params.name
<Route path="/files/*.*">
匹配 /files/hello.jpg 、 /files/hello.html
<Route path="/files/*">
匹配 /files/ 、 /files/a 、 /files/a/b exact // 完全匹配的意思,排他

Switch

有<Switch>嵌套,则其中的<Route>在路径相同的情况下,只匹配第一个,这个可以避免重复匹配。

无<Switch>嵌套,则其中的<Route>在路径相同的情况下全都会匹配,包括上级路径。

Rediret

重定向到新地址

<Redirect to='/path' />

Prompt

当用户准备离开该页面时,弹出提示

message: 字符串/函数,离开页面时的提示信息
when:布尔值,通过设定条件决定是否启用该组件

例如:

<Prompt message="您确定要离开该页面吗?" when={this.state.isOpen} />
<Prompt
message = {() => {this.state.isOpen? false: "您确定要离开该页面吗?"}}
/>

对象和方法

被Route绑定的渲染组件,总是被传入三个属性(对象):history、location、match。在渲染组件中也会有很多其他组件,这些组件内部如果想要获取三个对象,需要withRouter(通过装饰器或函数调用的形式都可)。

我们可以用这三个对象完成很多事情。

history

history实现对会话历史的管理。

length: number   浏览历史堆栈中的条目数
action: string 路由跳转到当前页面执行的动作,分为 PUSH, REPLACE, POP
location: object 当前访问地址信息组成的对象,具有如下属性:
pathname: string URL路径
search: string URL中的查询字符串
hash: string URL的 hash 片段
state: string 例如执行 push(path, state) 操作时,location 的 state 将被提供到堆栈信息里,state 只有在 browser 和 memory history 有效。
push(path, [state]) 在历史堆栈信息里加入一个新条目。
replace(path, [state]) 在历史堆栈信息里替换掉当前的条目
go(n) 将 history 堆栈中的指针向前移动 n。
goBack() 等同于 go(-1)
goForward 等同于 go(1)
block(prompt) 阻止跳转

location

loaction指当前的位置

{
hash: '#sdfas',
key: 'sdfad1'
pathname: '/about',
search: '?name=minooo'
state: {
price: 123
}
}

可以在不同场景中使用:

<Link to={location} />
<NaviveLink to={location} />
<Redirect to={location />
history.push(location)
history.replace(location)

match

match对象包含了<Route>如何与URL匹配的信息。

params: object 路径参数,通过解析 URL 中的动态部分获得键值对
isExact: bool 为 true 时,整个 URL 都需要匹配
path: string 用来匹配的路径模式,用于创建嵌套的 <Route>
url: string URL 匹配的部分,用于嵌套的 <Link>

路由之间的传值

大致有三种方法:

params

//路由设置
<Route path=' /user/:id ' component={User} />
// 传值
<Link to='/user/2' />
this.props.history.push("/user/2");
// 获取值
this.props.match.params.id

URL参数

//路由设置
<Route path=' /user ' component={User} />
// 传值
<Link to='/user?id=2' />
this.props.history.push("/user?id=2");
// 获取值
this.props.location.seacrh // 获得"?id=2",将其进行拆解即可获得

location对象(哈希路由无法利用)

又有两种方式:

(1)loaction.state。传的参数是加密的

// 路由设置
<Route path=' /user ' component={User}></Route>
// 传值
<Link to={{ pathname:' /user',state:{id:123},search:'?sort=name',hash:'#the-hash'}}>
this.props.history.push({pathname:' /user',state:{id:123},search:'?sort=name',hash:'#the-hash'});
// 获取值
this.props.location.state.id

(2)自定义属性

// 路由设置
<Route path=' /user ' component={User}></Route>
// 传值
<Link to={{ pathname:' /user',abc:{id:123},search:'?sort=name',hash:'#the-hash'}}>
this.props.history.push({pathname:' /user',abc:{id:123},search:'?sort=name',hash:'#the-hash'});
// 获取值
this.props.location.abc.id

导航守卫的实现

在react-router中,并没有提供导航守卫相关的API,作者这样描述:你可以在渲染功能中实现此功能,JSX不需要API,因为它更灵活。

首先,导航守卫在业务层面可能有三种表现:

  1. 根据状态(如登录/未登录)和身份(等级)将路由进行限制。低等级的用户根本没有定义某些路由。
  2. 路由在任何时候都是完整的,只是根据状态和身份,将入口进行限制(某些Link组件不显示)。没有任何操作能够导向没有权限访问的路由地址。
  3. 不对入口进行限制,根据状态和身份,将某些特定的路由添加拦截。

在这几种表现中,2和3并不相互冲突。现在有两种思路实现导航守卫:

  • 写一个路由配置表,写一个高阶组件,导航守卫的功能由高阶组件完成,所有与路由绑定的组件都被高阶组件修饰。(对应业务场景3)
  • 写一个路由配置表,定义一个组件:根据路由配置生成最终的<Route>。对于用户没有权限的路由,可以控制不将其渲染。(对应业务场景1)
  • 写一个路由配置表,写一个高阶组件,将是否渲染入口的逻辑写在高阶组件中,所有可能被隐藏的入口都被此高阶组件修饰。(对应业务场景2)

示例1(业务场景1):

// 路由配置
const routerConfig = [
{
path:'/',
component:HomePage,
auth:false,
},{
path:'/home',
component:HomePage,
auth:true, // 表示必须登录才能访问
},{
path:'/login',
component:LoginPage,
},{
path:'/404',
component:ErrorPage
}
]; class RouterTab extends React.Component{
render(){
return(
<HashRouter>
<Switch>
<RouteGenerator config={routerConfig} />
</Switch>
</HashRouter>
);
}
} class RouterGenerator extends React.Coponent{
// 在这里定义限制路由的逻辑(业务场景1)
render(){
const routeConf = this.props.config;
routeConf.map((conf)=>{
if(conf.auth) // 判断该路由是否满足渲染条件
{
if(login) // 判断当前有没有登录
{
retrun <Route path={conf.path} component={conf.component} exact={conf.exact?true:false} />
}
}else
{
retrun <Route path={conf.path} component={conf.component} exact={conf.exact?true:false} />
}
});
}
}

示例2(业务场景3):

// 将此高阶组件修饰所有需要被守卫的路由组件
const routerGuard = (RouteConfig) => {
retrun (WrappedComponent) => {
rentrun class NewComponent extends React.Component { componentWillMount(){
const path = this.props.location.pathname;
const config = RouteConfig.find(f => f.path === path);
if(!config)
{
this.props.history.push("/404");
}
if(config.auth && !login)
{
this.props.history.push("/login");
}
} render(){
retrun(
<WrappedComponent {...this.props} />
)
}
}
}
}

路由的异步加载

如果项目特别大,打包后的js文件会特别大。在首次加载时,一次性地将整个js文件发送给浏览器,一次性地加载所有代码,会对浏览器产生比较大的压力,影响用户体验。我们希望的是,只加载当前访问页面相关的js代码,当路由跳转的时候,再请求相应页面的js代码。这需要使用第三方库,做的比较优秀的有 react-loadable 和 react-async-component。

react-loadable的原理是将代码进行分割,分割成若干个chunk.js,需要用到的时候就请求过来。

react-async-component为按需异步加载,使用Promise和高阶组件实现,提高性能。

React-router总结的更多相关文章

  1. [Redux] Filtering Redux State with React Router Params

    We will learn how adding React Router shifts the balance of responsibilities, and how the components ...

  2. [转] React Router 使用教程

    PS:react-route就是一个决定生成什么父子关系的组件,一般和layout结合起来,保证layout不行,内部的子html进行跳转 你会发现,它不是一个库,也不是一个框架,而是一个庞大的体系. ...

  3. [Redux] Navigating with React Router <Link>

    We will learn how to change the address bar using a component from React Router. In Root.js: We need ...

  4. [Redux] Adding React Router to the Project

    We will learn how to add React Router to a Redux project and make it render our root component. Inst ...

  5. React Router基础使用

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...

  6. 最新的chart 聊天功能( webpack2 + react + router + redux + scss + nodejs + express + mysql + es6/7)

    请表明转载链接: 我是一个喜欢捣腾的人,没事总喜欢学点新东西,可能现在用不到,但是不保证下一刻用不到. 我一直从事的是依赖angular.js 的web开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...

  7. react router 4.0以上的路由应用

    thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr& ...

  8. React Router 使用教程

    一.基本用法 React Router 安装命令如下. $ npm install -S react-router 使用时,路由器Router就是React的一个组件. import { Router ...

  9. 关于react router 4 的小实践

    详细代码栗子:https://github.com/wayaha/react-dom-CY clone然后 npm install npm start 分割线 1.这个项目使用create-react ...

  10. React Router 4.x 开发,这些雷区我们都帮你踩过了

    前言 在前端框架层出不穷的今天,React 以其虚拟 DOM .组件化开发思想等特性迅速占据了主流位置,成为前端开发工程师热衷的 Javascript 库.作为 React 体系中的重要组成部分:Re ...

随机推荐

  1. iOS项目之多Targets和多环境配置

    项目中使用的同一套代码,但需要开发多个app,app中内容基本上相同,只有一些小小的区别,例如名称等等,每个app中又需要分开发环境(Dev).测试环境(Test).正式环境(Pro). 下面就开始搭 ...

  2. 状压DP概念 及例题(洛谷 P1896 互不侵犯)

    状压DP 就是状态压缩DP.所谓状态压缩,就是将一些复杂的状态压缩起来,一般来说是压缩为一个二进制数,用01来表示某一元素的状态. 比如一排灯泡(5个) 我们可以用一串二进制01串来表示他们的状态 1 ...

  3. 强化学习(Reinforcement Learning)中的Q-Learning、DQN,面试看这篇就够了!

    1. 什么是强化学习 其他许多机器学习算法中学习器都是学得怎样做,而强化学习(Reinforcement Learning, RL)是在尝试的过程中学习到在特定的情境下选择哪种行动可以得到最大的回报. ...

  4. Elasticsearch由浅入深(一)

    什么是Elasticsearch 什么是搜索 百度:我们比如说想找寻任何的信息的时候,就会上百度去搜索一下,比如说找一部自己喜欢的电影,或者说找一本喜欢的书,或者找一条感兴趣的新闻(提到搜索的第一印象 ...

  5. powerdesigner16.6版本resource的重复使用

    今天早上遇到想要重复使用resource ,但是发现powerdesigner16.6版本跟16.5版本有关重复使用name的设置已经不一样了,网上找了好久没找到,软件上找了好久也没找到相应的设置. ...

  6. 以帧为存储单位的循环stack

    此stack主要是作为存储空间使用,主要的借口就是push和pop. stack frame的src以及例程位于stack_FrameTest这个库当中,其中有readme文件,可以快速上手. sta ...

  7. mybatis 中 useGeneratedKeys 和 keyProperty 含义

    MyBatis如何获取插入记录的自增长字段值: 第一步: 在Mybatis Mapper文件中添加属性“useGeneratedKeys”和“keyProperty”,其中keyProperty是Ja ...

  8. Memcached的原理分析与配置

    一.Why Memcached? • 高并发访问数据库的痛楚:死锁! • 硬盘IO之痛:本机:AspNet:HttpRuntime.Cache • 多客户端共享缓存 • Net+Memory>& ...

  9. .NETCore Docker实现容器化与私有镜像仓库管理

    一.Docker介绍 Docker是用Go语言编写基于Linux操作系统的一些特性开发的,其提供了操作系统级别的抽象,是一种容器管理技术,它隔离了应用程序对基础架构(操作系统等)的依赖.相较于虚拟机而 ...

  10. java JVM原理讲解和调优和gc