三、React Router 5路由,路由传参

一、路由

1.1、 SPA的理解

1.单页Web应用(single page web application,SPA)。
2.整个应用只有一个完整的页面。
3.点击页面中的链接不会刷新页面,只会做页面的局部更新。
4.数据都需要通过ajax请求获取, 并在前端异步展现。

1.2、路由的理解

1.什么是路由?

1.一个路由就是一个映射关系(key:value)
2.key为路径, value可能是function或component

2.路由分类

后端路由:
1、理解: value是function, 用来处理客户端提交的请求。
2、注册路由: router.get(path, function(req, res))
3、工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
前端路由:
1、浏览器端路由,value是component,用于展示页面内容。
2、注册路由: <Route path="/test" component={Test}>
3、工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件

一、React Router 5

react-router-dom的理解

1、react的一个插件库。
2、专门用来实现一个SPA应用。
3、基于react的项目基本都会用到此库。

下载react-router-dom:

npm install --save react-router-dom

内置组件
1、<BrowserRouter>:用于将应用程序包裹在 HTML5 history API 的 <BrowserRouter> 中,使得 React Router 可以监听 URL 的变化,并且匹配当前 URL 对应的 Route 进行渲染。
2、<HashRouter>:用于将应用程序包裹在 hash history 的 <HashRouter> 中,适用于不支持 HTML5 history API 的环境,如旧版浏览器或一些特殊环境。
3、<Route>:用于声明路由规则,即指定路径对应的组件渲染内容。<Route> 根据当前 URL 路径匹配对应的路径规则,并渲染相关组件。
4、<Redirect>:用于在匹配到某个路径时重定向到另一个路径,可以用于处理一些特殊场景,比如用户访问的旧路径需要重定向到新路径。
5、<Link>:用于在应用中创建导航链接,点击该链接后会更新 URL 而不会重新加载页面,实现单页应用的导航功能。
6、<NavLink>:是 <Link> 的一个增强版本,除了具有 <Link> 的功能外,还可以添加 activeClassName 和 activeStyle 等属性,用于定义链接激活时的样式。
7、<Switch>:用于包裹多个 <Route> 组件,它会遍历所有子 <Route> 组件,并只渲染与当前 URL 匹配的第一个 <Route> 或 <Redirect> 组件,避免多个路由同时匹配的问题

1.1、BrowserRouter 和 HashRouter 的区别

1.底层原理不一样
  BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。HashRouter使用的是URL的哈希值。
2.path表现形式不一样
  BrowserRouter的路径中没有#,例如: localhost:3000/demo/test
  HashRouter的路径包含#,例如: localhost:3000/#/demo/test
3.刷新后对路由state参数的影响
  (1).BrowserRouter没有任何影响,因为state保存在history对象中。
  (2).HashRouter刷新后会导致路由state参数的丢失!!!

原生html中,靠<a>跳转 不同的页面
              <a href="./about.html">About</a>
              <a href="./home.html">Home</a>

在React中靠路由链接实现切换组件
首先我们把about.html和home.html改成两个组件
然后引入 Link 和 Route ,通过<Route>注册路由,通过 <Link />进行切换组件

import {HashRouter, Link , Route} from "react-router-dom";

hash路由模式
<HashRouter>
  跳转路由
  <Link to="/about" />
  <Link to="/home" />
  注册路由
  <Route path="/about" component={About}></Route>
  <Route path="/home" component={Home}></Route>
</HashRouter>

1.2、<NavLink>是<Link>的一个特定版本,会在匹配上当前的url的时候给已经渲染的元素添加参数,组件的属性有:

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

路由的基本使用

import { HashRouter, Route, NavLink } from "react-router-dom";
<HashRouter>
 跳转路由
  <NavLink to="/about" />
  <NavLink to="/home" />
  注册路由
  <Route path="/about" component={About}></Route>
  <Route path="/home" component={Home}></Route>
</HashRouter>

1.3、Switch和Redirect

当我们注册路由,注册了同样的路径,渲染不同的路由组件,当跳转路由的时候有两个路由能匹配上就会出现两个路由组件全部展示的情况,如下图

  <Route path="/home" component={Home}></Route>
  <Route path="/home" component={Test}></Route>

正常来说一个路径匹配一个路由,上图明显有问题,如果每个同样的路径匹配多个路由组件,如果我们要展示两个路由组件为什么不把两个路由组件合成一个组件呢,当第一个路由组件匹配上以后,如果下面还有无数个相同路径的路由组件,会匹配无数次路由会导致性能损耗,所以一个路径匹配一个路由。这个时候我们会使用Switch:Switch实现提高匹配效率的效果,匹配到第一个后面就不会匹配了

<Switch>
  <Route path="/about" component={About}></Route>
  <Route path="/home" component={Home}></Route>
  <Route path="/home" component={Test}></Route>
 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
  <Redirect to="/about" />
</Switch>

路由的严格模式


如上图,我们注册的路由组件路径和跳转路由的开始的路径能匹配上,就能正常展示路由组件的页面,如下图,跳转的路径是 /home/index,注册路由的地址是 /home,因为跳转路径前面的地址是 /home,默认是模糊模式,所以成功匹配展示注册路由组件
如果需要注册的路由组件路径和跳转路由的开始的路径完全一样:

路由开启严格匹配
严格模式不要随便开启,这样会影响二级路由
<Route exact path="/about" component={About}></Route>第一种方法,写exact属性就行
<Route exact={true} path="/home" component={Home}></Route>第二种方法,写exact={true}

嵌套路由

这里是父组件,正常写路由就行
<Switch>
  <Route path="/about" component={About}></Route>
  <Route path="/home" component={Home}></Route>
  <Redirect to="/about" />
</Switch>

这里是子路由的组件,子路由注册的时候需要加上父组件的路径
<Switch>
  <Route path="/home/news" component={News}/>//嵌套路由需要加上父路径
  <Redirect to="/home/news"/>
</Switch>

React Router 5路由传参

跳转路由
 向路由组件传递params参数 
 <Link to={`/home/message/detail/${i.id}/${i.title}`}  children={i.title} />
 向路由组件传递search参数  
 <Link to={`/home/message/detail/?id=${i.id}&title=${i.title}`}  children={i.title} />
 向路由组件传递state参数  
  <Link to={{pathname: "/home/message/detail", state: {id:i.id,title:i.title}}}  children={i.title} />

注册路由
 声明接收params参数
 <Route path="/home/message/detail/:id/:title" component={Detail} />
 search参数无需声明接收,正常注册路由即可
 <Route path="/home/message/detail" component={Detail} />
 state参数无需声明接收,正常注册路由即可
 <Route path="/home/message/detail" component={Detail} />

路由组件接受路由参数
 接收params参数
 const {id, title} = this.props.match.params;
 接收search参数
 import qs from "querystring";
 const {id, title} = qs.parse((this.props.location.search).slice(1));
 接收state参数
 const {id, title} = this.props.location.state || {};

接收search参数,需要下载querystring  npm i querystring
querystring基本使用
import qs from "querystring";

let obj = { name: 'tom', age: 18}; //name=tom&age=18 key=value&key=value
console.log(qs.stringify(obj));

let str = 'carName=奔驰&price=199';
console.log(qs.parse(str));

路由跳转模式push和replace
push(/path) 里面的path会进入路由栈,
replace(/path) 不会,但是它里面的path会替换掉路由栈里最后一个路由

路由跳转开启replace模式,默认是push模式
<Link to={`/home/message/detail/${i.id}/${i.title}`} replace={true} children={i.title} />

编程式路由

通过按钮触发方法,方法里进行路由跳转
  <button onClick={() => this.pushShow(i)}>Push查看</button>
  <button onClick={() => this.replaceShow(i)}>Replace查看</button>

注册路由
  接收params参数
  <Route path="/home/message/detail/:id/:title" component={Detail} />
  search参数无需声明接收,正常注册路由即可
  <Route path="/home/message/detail" component={Detail} />
  state参数无需声明接收,正常注册路由即可
  <Route path="/home/message/detail" component={Detail} />

跳转路由
replaceShow = (i) =>{
    replace跳转+携带params参数
    this.props.history.replace(`/home/message/detail/${i.id}/${i.title}`)
    
    replace跳转+携带search参数
    this.props.history.replace(`/home/message/detail?id=${i.id}&title=${i.title}`)
    
    replace跳转+携带state参数
    this.props.history.replace(`/home/message/detail`,{...i})
}
pushShow = (i) =>{
    push跳转+携带params参数
    this.props.history.push(`/home/message/detail/${i.id}/${i.title}`)
    
    push跳转+携带search参数
    this.props.history.push(`/home/message/detail?id=${i.id}&title=${i.title}`)
    
    push跳转+携带state参数
    this.props.history.push(`/home/message/detail`,{...i})
}

路由组件接受路由参数
 接收params参数
 const {id, title} = this.props.match.params;
 接收search参数
 import qs from "querystring";
 const {id, title} = qs.parse((this.props.location.search).slice(1));
 接收state参数
 const {id, title} = this.props.location.state || {};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容