react-day03(Router)
(1)路由介绍---根据url路由不同渲染不同组件
1、安装
npm install --save react-router-dom
安装完毕后,查看package.json项目说明文件,此时该开发依赖已经分配到生产依赖dependencies中

审查后发现该版本为5版本系列,5版本主要针对React Hook做了更好的支持
2、作用

点击不同导航选项时会跳到不同的对应页面,而React主要编写单页面应用(SPA):所有的页面跳转都是由路由操作,主要原理是根据路由不同去切换试图。
SPA页面跳转:
所有的页面跳转都是由路由操作,主要原理是根据路由不同去切换试图
接下来优化下项目初始结构,删除无用文件(serviceWorker.js离线缓存。。。)

并修改入口文件

根组件App.js也做下简化

效果如下所示

但一个应用不可能只有一个页面,所以借着下面操作

之后编写相关组件并导出

除了使用Class类的形式,使用function形式也可以创建组件,如下

接下来在根组件引入

接下来想要的效果是根据路径不同,显示不同的组件页面,类似于百度新闻


首先引入Router的一系列方法
import {BrowserRouter as Router,Switch,Route,Link} from 'react-router-dom'
分析:因为BrowserRouter单词过长,所以这里官方推荐我们用as重命名为Router;Router代表路由器,而Route代表线路;Link用于跳转
接下来结合Route便可以实现路由渲染,如下所示

测试如下

至此便可以实现根据不同的url路由渲染不同组件。
(2)BrowserRouter与HashRouter区别


接下来我们看下两者区别
1、BrowserRouter

表现形式如下

2、HashRouter

表现形式如下

3、区别
HashRouter表现为锚点链接
BrowserRouter没有锚点形式,以斜杠开头,但不能以斜杠结尾。是H5 新特性,主要通过history.push实现。上线之后,需要配合后台进行相关处理(重定向处理404的BUG)
由于此技术仅旨在支持旧版浏览器,因此我们建议配置服务器以供使用<BrowserHistory>。
(3)Router之Link跳转


本质会被解释为a标签
此时便可以点击导航进行页面展示内容的切换。
接下来将Link换为a链接做下测试

此时仍旧可以实现页面切换跳转。但两者仍存在较大差异,直接用a链接虽然可以跳转,但违背了SPA的初衷,每次跳转都会重新加载相同信息。
正常开发,一般会将该导航组件单独分隔出去,所以借着处理如下



(4)Router之exact匹配规则---精准匹配
需求:访问链接为http://localhost:5000/mine/info时,页面展示info信息组件


此时做下测试

会发现,除了展示Info组件,Mine组件也展示了出来。此时便可以利用exact精准匹配
<Route path="/mine" exact={true} component={Mine}></Route>
默认exact为true,所以,也可以不写赋值。借着做修改,一般访问首页都不带home,所以修改如下


测试如下,会发现每个页面都会将Home组件渲染出来

修改如下,利用exact进行精准匹配,即可解决该问题

(5)Router之strict严格匹配
虽然之前的exact可以进行精准匹配,但某些情况下还不够
场景:有时,我们访问网站时习惯在最后加个/,但开发者并不希望匹配到它。因为有时最后的/可能表示另外一个路径,此时可以通过strict来处理

接下来添加严格匹配属性,处理后的结果如下所示


另外,还有一点要注意,exact精准匹配存在的组件想要添加严格匹配strict时,两者同时存在,不然会无效。

(6)Router之404页面和Switch
当用户访问的url不存在时,做出对应404页面反馈

编写如下


之后进行导入使用

因为是全规则匹配,所以不用添加path,此时测试如下

但此时会发现,每个页面都会渲染404组件

此时便可以利用Switch进行限制,在Switch下只能显示一个组件

(7)Router之render function简约加载方案------加载组件的另一种方式
之前的每个视图都对应一个组件,但有时也可以使用简约方案,来代替简单的组件


除了直接render里写标签内容外,还可以直接调用组件。即将标签内容直接替换为组件调用

而且这种方式也可以传递参数,如下所示


结果如下

这些信息在以后操作会有相关作用。当然,也可以传递其他基本类型数据,如下所示



此外也可以利用解构赋值格式,如下

以上便是极简形式的渲染方法,可以不用component属性,利用render进行直接渲染,也可以手动传递参数
参数传递与路径展示:且该参数没有在路径上进行相关展示,之后会介绍其他参数传递,可以在路径上进行展示
(8)Router之NavLink激活导航高亮


如上所示,在不同页面时,导航会有对应的高亮展示,这时便需要用到<NavLink></NavLink>

接下来对代码做下修改,将所有的Link换为NavLink

接下来坐下测试,此时仍然可以正常切换

此时会发现,被选中的导航,会添加className为active,所以接下来可以给该类名添加样式

然后在Nav.jsx组件引入

测试如下

会发现,在other下除了other对于导航,home首页也被高亮。
原因:
/other包裹在/首页下,所以需要添加exact精准匹配

除了默认的active,也可以自定义激活状态的类名,使用属性activeClassName即可



接着,编写navSelected样式即可
此外也可以使用内联样式style进行状态编写,如下所示

如果activeStyle要直接写到标签里,则需要使用{{}}才可以,如下所示

(9)Router之url parameters---路由传参(单个或多个)---参数传递形式1---parameters参数形式
对于某些页面来说,渲染时传递的参数不同,会导致渲染不同内容。这时便需要通过路由传参进行处理了。这里我们用/mine/info来举例

传递参数时以/开头
<Route path="/mine/info/:id" component={Info}></Route>
此时跳转的组件里,便可以通过props进行接收。在info组件输出测试下


此时便可以通过props.match.params.id来获取传递的id参数


此时便可以根据传参的不同,获取到不同的网络数据
但此时仍然存在,问题,如果不传递参数,会出现404错误,如下所示

此时可以加个参数?,表示传参可有可无,如果不传参数,则默认无即可
<Route path="/mine/info/:id?" component={Info}></Route>

此外,也可以传递多个参数,如下所示
<Route path="/mine/info/:id?/:name?/:age?" component={Info}></Route>


真正开发时,不可能让用户手动传递,一般都是点击跳转时传递,如下所示


<NavLink></NavLink>导航处传递,<Route path="/mine/info/:id?/:name?/:age?" component={Info}></Route>处接受渲染。
(10)Router之url query string---路由传参(单个或多个)---参数传递形式2---query问号形式
除了上述参数传递形式
,还有另外一种形式
如果是query问号形式,则可以通过location.search来获取,如下所示

所以接下来有两种读取方案
1、读取方案一:new URLSearchParams(props.location.href).get(name)


接着使用get方法传入对应参数名获取对应值,如下所示

此外还有第二种读取方案,较为简单
2、读取方案二:引入querystring依赖包,然后调用该依赖包的相关方法

测试结果如下

但此时对象前面有个?,如果不去掉则会影响id的读取,所以接着操作如下(转为字符串后,利用正则匹配将其替换)
JSON.stringify(queryParamsObject).replace(/\?/g,"")


(11)Router之to=object(该属性在Link和NavLink的表现一致)+ 隐藏属性state

这里我们拿mine组件导航来举例

接下来在Mine组件做下输出测试

此时点击导航如下所示

分析:此时可以读取到路由设置传参对象里的相关配置,例如通过hash做一些判断等等。。。 此外,还有一个隐藏属性state,不会表现在url里,但是隐性的传递了过来


此外,该隐藏属性可以自定义


state隐性属性优点:可以隐藏传递参数
(12)Router重定向之redirect
1、基础形式,基本用法

此时访问/hello时重定向到/,访问/hellomine时重定向到/mine
表现形式为直接在url进行拦截重定向,此外还有另外一种形式,即跳到新页面后再重定向到其他页面
2、跳转新页面后再进行重定向
场景:选择商品或外卖进行下单时,如果没有登录,则会重定向跳转到登录页面
首先编写商品页面组件,如下所示


测试如下

接下来做个功能,进入该商品页面后重定向到首页。所以首先需要判断登录状态

如果isLogin为true则是已经登录,直接展示该页面的相关信息,否则利用Redirect重定向到首页
这里便可以通过重定向Redirect实现权限功能
(13)Router重定向之push和replace
在mine我的页面点击按钮,重定向到首页
注意:这里我们用的其他方式编写方法,详情见React.Component三种手动绑定this方法,React创建组件的3种写法 ,React.createClass与React.Component区别.
這裡,我們輸出下props


除了上述写法,也可以直接通过this.props操作

所以可以根据push和replace方法操作进行自定义编码重定向,如下所示

两者区别: 1、push为叠加型,上次访问的页面依然存在内存里,可以通过返回键返回上一页 2、replace为替换型,直接替换掉上个页面,无法返回
场景:登录成功后,在接下来利用编码跳转到某个页面
(14)Router之withRouter高阶组件
有时,如果导航操作,没有放置在Router对象下,则组件不会被路由管理,所以没有路由对象。此时如果想在该组件操作路由,需要结合withRouter高阶组件实现
首先编写MineChild组件,作为Mine组件的子组件,然后在Mine组件里调用,如下所示

之后在Mine组件里引用


此时输出空对象,即props为空对象。
原因:
该组件没有放置在Router对象下,则组件不会被路由管理,所以没有路由对象。此时如果想在该组件操作路由,需要结合withRouter高阶组件实现。如下所示

此时this.props输出如下

接下来便可以进行路由操作了,如下所示

(15)Router之prompt---离开确定组件
场景:当前页面有输入框,且里面输入了一些内容,在离开该页面组件时,可能需要提示用户。即类似于钩子函数,在进行路由跳转前进行的一些操作
首先编写组件输入框代码,如下所示


此时输入内容后,离开该页面组件时没有任何提示。所以接下来给其添加提示操作。这里便用到了Prompt

这里使用了正则表达式/^s*$/匹配空行,此时离开页面,进行路由跳转时,会进行输入监听,如下所示

(16)Router之路由嵌套
新建书籍组件BookList,在其下进行路由嵌套


之后在入口文件,进行路由嵌套,如下所示

最终效果如下


.

浙公网安备 33010602011771号