前面的话

  路由用来分发请求。后端是提供服务的,所以它的路由是在找controller,前端是显示页面的,所以它的路由是在找component。本文将详细介绍react-router-dom的内容

Router

  Router是路由器组件的低阶接口,通常会使用如下某个高阶router来替代它

<BrowserRouter>
<HashRouter>
<MemoryRouter>
<NativeRouter>
<StaticRouter>

【BrowserRouter】

  最常用的是BrowserRouter

import { BrowserRouter } from 'react-router-dom'

<BrowserRouter
basename={optionalString}
forceRefresh={optionalBool}
getUserConfirmation={optionalFunc}
keyLength={optionalNumber}
>
<App/>
</BrowserRouter>

  1、basename: 当前位置的基准 URL。如果页面部署在服务器的二级(子)目录,需要将 basename 设置到此子目录。 正确的 URL 格式是前面有一个前导斜杠,但不能有尾部斜杠

<BrowserRouter basename="/calendar"/>

  2、getUserConfirmation:当导航需要确认时执行的函数。默认使用 window.confirm

// 使用默认的确认函数
const getConfirmation = (message, callback) => {
const allowTransition = window.confirm(message)
callback(allowTransition)
} <BrowserRouter getUserConfirmation={getConfirmation}/>

  3、forceRefresh:当设置为 true 时,在导航的过程中整个页面将会刷新。 只有当浏览器不支持 HTML5 的 history API 时,才设置为 true

const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory}/>

  4、keyLength:location.key 的长度。默认是 6

<BrowserRouter keyLength={}/>

  5、BrowserRouter只能渲染单一子元素

Route

  Route是react-router中最重要的组件,用来匹配请求并渲染相应组件

  1、path 路径的匹配值,可以包括以下几种特殊符号

:paramName – 匹配一段位于 /、? 或 # 之后的 URL。 命中的部分将被作为一个参数
() – 在它内部的内容被认为是可选的
* – 匹配任意字符(非贪婪的)直到命中下一个字符或者整个 URL 的末尾,并创建一个 splat 参数

  例子如下所示:

<Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
<Route path="/hello(/:name)"> // 匹配 /hello, /hello/michael 和 /hello/ryan
<Route path="/files/*.*"> // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg

  [注意]Route组件不能像普通组件一样,以属性的形式传递参数,但可以通过path属性来传递。但一定要区分router后面的:_id或:id

'/category/:_id'

  2、component 要显示的组件

import { BrowserRouter as Router, Route } from 'react-router-dom'

<Router>
<div>
<Route exact path="/" component={Home}/>
<Route path="/news" component={NewsFeed}/>
</div>
</Router>

  3、render 函数中return的值就是要显示的内容

<Route path="/home" render={() => <div>Home</div>}/>

  4、children与render的区别在于,不管有没有匹配,都想显示的内容

const ListItemLink = ({ to, ...rest }) => (
<Route path={to} children={({ match }) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest}/>
</li>
)}/>
)

  [注意]component/render/children只能三个选一个使用

【匹配规则】

  默认地,路由进行宽松匹配。在下面例子中,路由匹配到/one时,既显示组件A,也显示组件B

<Route  path="/one" component={A}/>
<Route path="/one/two" component={B}/>

  如果要进行确切匹配,则需要添加exact属性。这样,路由匹配到/one时,只显示组件A

<Route  exact path="/one" component={A}/>
<Route path="/one/two" component={B}/>

  还有一种是严格匹配,即斜杠也必须严格匹配。下面例子中,路由匹配到/one/时,会显示组件A,但匹配到/one时,什么都不会显示

<Route  strict path="/one/" component={A}/>

  [注意]严格匹配并不是确切匹配。下面例子中,路由匹配到/one时,即显示组件A,也显示组件B

<Route  strict path="/one" component={A}/>
<Route path="/one/two" component={B}/>

  如果要确切匹配,则需要

<Route  exact strict path="/one" component={A}/>

  但是,一般地,strict属性很少使用

【属性】

  Route默认携带三个props:包括match、location、history

  如果使用component,则使用this.props来获取,如果是render,则在回调函数中使用参数(props)=>{}来获取

  1、match

  match包括以下属性

params 键值对
isExact 是否确切匹配
path 路径中设置的值
url URL中的path值

  2、location

  location中包含如下属性

  [注意]直接访问location,而不是访问history.location

{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere'
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}

  通过Link传递的state,可以在location中获取到

  [注意]刚开始时,或者直接刷新浏览器,state是没有值的,只有跳转到该链接时,state才有值。再后来,刷新也有值了

  3、history

  history包含如下属性

length: history栈的长度
action: 当前的action
location: 当前的location对象

  history包含如下方法

push()
goBack() = go(-)
goForward() = go()
go() 跳转到 history栈中的哪个enter
replace(path, [state]) 替换history栈中的当前entry
push(path, [state]) 添加当前entry到history栈中

Redirect

  Redirect将页面导航到新位置,新位置将覆盖history栈中的当前位置,类似于服务器端的重定向(HTTP 3xx)

  to属性可以是一个字符串,表示跳转的地址

<Route exact path="/" render={() => (
loggedIn ? (
<Redirect to="/dashboard"/>
) : (
<PublicHomePage/>
)
)}/>

  to属性也可以是一个对象

<Redirect to={{
pathname: '/login',
search: '?utm=your+face',
state: { referrer: currentLocation }
}}/>

  push属性为true时,表示添加新记录到history栈中,而不是替换当前记录

<Redirect push to="/somewhere/else"/>

Link

  Link是对a标签的封装,提供无刷新的页面跳转。Link标签主要的属性是to属性

  1、一般地,to是一个字符串

<Link to="/about">关于</Link>

  2、也可以写成对象的形式

<Link to={{
pathname: '/courses',
search: '?sort=name',
hash: '#the-hash',
state: { fromDashboard: true }
}}/>

  [注意]在Link里的子组件或同组件的点击事件,最好加上阻止默认行为和阻止冒泡

<Link>
<div onclick={}></div>
</Link>
<Link onclick={}>

【NavLink】

  NavLink相对于Link来说,增加了一些样式属性

  activeClassName表示被匹配的a标签的样式名;activeStyle表示被匹配的a标签的样式

<NavLink
to="/faq"
activeClassName="selected"
>FAQs</NavLink>
<NavLink
to="/faq"
activeStyle={{
fontWeight: 'bold',
color: 'red'
}}
>FAQs</NavLink>

  注意: link和history.push都不支持指向外网地址,如果要跳转到外网,则需要使用window对象下的location对象

  

Switch

  渲染Route或Redirect匹配到的第一个子元素

<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>

  [注意]switch必须直接包括Route,中间不可包含div,否则不生效

跳转

  如果在实现逻辑跳转,可使用如下代码实现

// utils/history.js
import createBrowserHistory from 'history/createBrowserHistory'
const customHistory = createBrowserHistory()
export default customHistory

  引用如下

import  history  from '@/utils/history'
// 跳转到首页
history.push('/')

  要特别注意的是,如果使用utils/history.js,需要使用Router history={history},而不是BrowserRouter

  因为全局只能有一个history实例。 使用import { BrowserRouter as Router } 语句,会自动创建一个history实例的,相当于有两个实例,则会出现URL发生变化,刷新页面后,页面才跳转的情况

import { Router, Route, Switch, Redirect } from 'react-router-dom'
import history from '@/utils/history' <Router history={history}>
<Switch>
<Route path="/login" component={Login} />
<Route path="/" render={props => {if (sessionStorage.getItem('token') && sessionStorage.getItem('user')) {return <Home {...props} />
}
return <Redirect to="/login" />
}} />
</Switch>
</Router>

【传参】

  history.push方法也可以携带参数,方法如下

history.push({
pathname: '/about',
search: '?the=search',
state: { some: 'state' }
})

基础案例

import React from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom' // 三个基础呈现组件 const Home = () => (
<div>
<h2>Home</h2>
</div>
) const About = () => (
<div>
<h2>About</h2>
</div>
) const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
) // 一个内嵌的组件 const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul> <Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
) // 首页组件 const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul> <hr/> <Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
export default BasicExample

exact

  exact表示路由需要确切匹配,容易忽略的一点是,它与redux也有着非常密切的关系

  下面的代码是常见的增删改查的路由设置

<Switch>
<Route path="/post/add" component={AddPost} />
<Route exact path="/post/:id" component={ShowPost} />
<Route path="/post/:id/update" component={UpdatePost} />
<Route path="/post/:id/delete" component={DeletePost} />
</Switch>

  代码中,通向showPost的路由设置了exact。一般地,showPost通过fetch获取了post,并保存到store中的state.post中

  如果此时点击到updatePost中,可以通过state.post来得到值。而如果在updatePost页面直接刷新的话,则state.post值为空

  如果要确保页面刷新后仍然能够取得值,则需要通过route中的location传值

  但是,这种方法有两个缺陷。一个是不访问showPost,而直接访问UpdatePost不会获得传递的值;另一个是直接在地址栏中更改URL也不会获取传递的值

  2、去掉exact和switch,同时需要更改样式和路由。使得path="/post/:id/update"时,可以同时匹配ShowPost和UpdatePost,且UpdatePost的页面可以完全覆盖ShowPost的页面

<Route path="/posts/add" component={AddPost} />
<Route path="/post/:id" component={ShowPost} />
<Route path="/post/:id/update" component={UpdatePost} />
<Route path="/post/:id/delete" component={DeletePost} />

  但是,由于这种方法对样式的定制化需求较高,都需要设置为定位元素,且根据覆盖关系来确定z-index。并且页面尺寸都需要保持一致。可扩展性不强

react-router简明学习的更多相关文章

  1. React Router V4.0学习笔记

    最近在学习React Router,但是网站的教程多半还是3.X版本之前的,所以我只能在GitHub上找到React Router的官方文档在读.后来总结了一下,包括学习经验以及V3.X与V4.X的差 ...

  2. React Router学习

    React Router教程 本教程引用马伦老师的的教程 React项目的可用的路由库是React-Router,当然这也是官方支持的.它也分为: react-router 核心组件 react-ro ...

  3. 初步学习React Router 4.0

      React Router 4.0 是react官方推荐的路由库.4是已经正式发布的最新版本. 初始化项目启动之后: npm run eject 弹出配置文件.自定义配置webpack 查看下pac ...

  4. React Router学习笔记(转自阮一峰老师博客)

    React Router是一个路由库,通过管理URL来实现组件切换和状态转变. 1.安装和使用 $ npm install -S react-router 在使用时,作为React组件导入 impor ...

  5. WebPack 简明学习教程

    WebPack 简明学习教程 字数1291 阅读22812 评论11 喜欢35 WebPack是什么 一个打包工具 一个模块加载工具 各种资源都可以当成模块来处理 网站 http://webpack. ...

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

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

  7. React Router API文档

    React Router API文档 一.<BrowserRouter> 使用HTML5历史记录API(pushState,replaceState和popstate事件)的<Rou ...

  8. [Web 前端] 你不知道的 React Router 4

    cp from https://segmentfault.com/a/1190000010718620 几个月前,React Router 4 发布,我能清晰地感觉到来自 Twitter 大家对新版本 ...

  9. [Web 前端] React Router v4 入坑指南

    cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子 ...

  10. React躬行记(13)——React Router

    在网络工程中,路由能保证信息从源地址传输到正确地目的地址,避免在互联网中迷失方向.而前端应用中的路由,其功能与之类似,也是保证信息的准确性,只不过来源变成URL,目的地变成HTML页面. 在传统的前端 ...

随机推荐

  1. MySQL之pymysql模块

    MySQL之pymysql模块   import pymysql #s链接数据库 conn = pymysql.connect( host = '127.0.0.1', #被连接数据库的ip地址 po ...

  2. Dijkstra and Floyd算法

    Dijkstra算法 算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集 ...

  3. 简化的CDN架构分析

    CDN架构的设计目标是通过复制系统资源(即Web服务器)的方式来获得高性能和高扩展性,为了能确保在海量内容下可以稳定提供高性能的服务.系统资源的复制可以在本地和地理两个尺度上进行.如果是本地复制则响应 ...

  4. Java中的Lock与synchronized

    并发编程学习笔记之Lock与synchronized 一.什么是可重入锁 Lcok在Java中是一个接口,一般在面试问题中问到的可能是ReentrantLock与synchronized的区别.Ree ...

  5. mongodb副本集中其中一个节点宕机无法重启的问题

    2-8日我还在家中的时候,被告知mongodb副本集中其中一个从节点因未知原因宕机,然后暂时负责代管的同事无论如何就是启动不起来. 当时mongodb的日志信息是这样的: 实际上这里这么长一串最重要的 ...

  6. Android自定义Seekbar滑动条,Pop提示跟随滑动按钮一起滑动

    由于项目需要做出此效果,自定义写了一个. 效果图 思路: 原始的seekbar只有滑动条并没有下方的提示文字,所以我们必须要继承Seekbar重写这个控件. 代码: 在values文件夹下新建attr ...

  7. cips2016+学习笔记︱NLP中的消岐方法总结(词典、有监督、半监督)

    歧义问题方面,笔者一直比较关注利用词向量解决歧义问题: 也许你寄希望于一个词向量能捕获所有的语义信息(例如run即是动车也是名词),但是什么样的词向量都不能很好地进行凸显. 这篇论文有一些利用词向量的 ...

  8. setsockopt()用法(参数详细说明) recv、send的超时处理

    源于recv send 阻塞和非阻塞 int setsockopt(SOCKET s,int level,int optname,const char* optval,int optlen); s(套 ...

  9. AM335x(TQ335x)学习笔记——WM8960声卡驱动移植

    经过一段时间的调试,终于调好了TQ335x的声卡驱动.TQ335x采用的Codec是WM8960,本文来总结下WM8960驱动在AM335x平台上的移植方法.Linux声卡驱动架构有OSS和ALSA两 ...

  10. js小括号的作用

    js中小括号()的用法详解:对于小括号无论是菜鸟还是高手一定都不会陌生,可以说它几乎是随处可见,虽然熟悉但并非真正的理解,由此可能会产生很多莫名其妙的错误,下面就通过代码实例详细介绍一下小括号的用法. ...