本章先来讲讲关于React-Router 第5版的相关知识,在之后的章节中也会介绍更新的第6版本
目前我们编写的应用大部分还是单页应用(SPA),也就是说不同的页面都是对应一个 url地址。一旦刷新,整个应用重新加载,返回首页,所有的操作都要重新进行。
React-router为我们提供一种称为客户端路由 的东西,通过客户端路由,可以将URL地址和React组件进行映射。当URL地址发生变化的时候,它会根据设置自动切换到指定的组件【也就是与其对应的组件会自动挂载】,并且这种切换完全不依赖于服务器。在用户看来浏览器的地址确实发生了变化,但是这一变化并不由服务器处理,而是通过客户端路由进行切换。
React-router最新版本为6(更便捷但还没完善),版本6与版本5之间变化大。
安装:npm install react-router-dom@5 -S-
配置
首先,引入react-router-dom包;
接着,在index.js中引入BrowerRouter组件;
最后,将BrowserRouter作为一个根标签,设置为根组件
放到<BrowserRouter>标签中的标签,都能够使用router了
同样我们也可以给它起个别名:
使用-映射
例如在App.js下,使用Route来映射地址和组件。
<Route path="映射的url地址" component={要挂载的组件名}/>
注意默认情况下Router并不是严格匹配,只要url地址的头部和path一致,组件就会挂载。添加一个属性exact实现严格匹配。
<Route exact path="映射的url地址" component={要挂载的组件名}/>
或者,也可以这样映射:
跳转超链接
注意,在使用react-router时,一定不要使用a标签来创建超链接,否则相当于每一次点击链接,都会重新加载整个应用,对性能浪费很大。我们希望的是所有的调转都在前端进行。
我们要使用**<Link to ="url"></Link>**来代替超链接。
Menu.js组件:
除了Link,还能使用 <NavLink to ="url"></NavLink>
Navlink与Link作用相似,但是有一个好处就是,可以设置属性activeClassName,实现当页面显示相应组件的时候,对应的链接变成相应的颜色。
或者还能使用activeStyle属性来设置:
两种router
HashRouter,BrowserRouter
- HashRouter
使用这一种react-router生成的url地址带一个井号#,表示哈希值。会通过url中的hash值来对地址进行匹配。
- BrowserRouter
直接通过url地址进行组件的跳转,使用过程中和普通的url地址没有区别。
当我们通过点击Link构建的链接进行跳转的时候,跳转没有经过服务器,所以没有问题;**当我们刷新页面或者通过普通链接进行跳转时,会向服务器发送请求加载数据。**也就是说这时候的请求没有经过react-router,所以有可能会找不到页面,404报错。
上述问题的解决方法:
-
第一种:使用HashRouter。服务器不会去判断hash值,所以使用HashRouter后请求将会由React-Router处理
-
第二种:**修改服务器配置。**将所有请求都转发到index.html. 进而交给react来处理。
可以使用nginx开启本地服务器
Route组件
- 属性(1)component属性
<Router>中的component属性用来指定路由匹配后被挂载的组件,它需要直接传递组件的类。
通过component构建的组件,它会自动创建组件并且会自动传递参数。
match -- 匹配的信息
isExact检查路径是否完全匹配
params请求的参数
path 规则路径
url
location -- 地址信息
hash:
pathname:地址信息
search:查询字符串
state:传递的数据
history -- 控制页面的跳转 和DOM中的histry类似
可以通过调用方法来实现跳转等功能。
push() 作用就是跳转页面 需要一个location作为参数
使用push 会产生一个新的历史记录,可以通过回退按钮返回到原先的页面。
replace() 替换页面 直接把当前的记录替换掉。
在组件中,需要使用props来访问到上述传递的参数。
关于params:
然后如果我们的路由是: xxx/student/4
这里的传入的4 就可以在Student组件中通过 props.match.params来获取。==> id:4
这样,我们就可以通过路由来给组件传递参数,让组件通过不同的参数来加载不同的数据。
- 属性(2)render属性
使用Route中的render属性,同样可以实现component组件的效果,也可以指定要挂载的组件。
render需要一个回调函数作为参数,回调函数的返回值会最终被挂载
在render中,组件可以通过JSX形式来传递,**这样我们就可以自定义要传递的参数。**不会自动传递上述的三个属性(match,location,history) ,我们可以使用routePros来传递这三个属性,或者单独传递。
render相比component要更加灵活。
- 属性(3)children属性 router6中废弃了
children属性也可以用来指定被挂载的组件。两种用法:<1> 和render类似,传递回调函数。[当children设置一个回调函数时,该组件无论路径是否匹配,都会挂载]
<2> 可以传递组件
在被路由的组件中,除了可以通过props来获取三个对象之外,也可以通过钩子函数直接获取:
路由的嵌套
在下面这个代码中,只有当我访问的地址是/about/hello时,才能访问到<Hello/>组件:
嵌套的逻辑除了可以定义到App.js中,还能直接定义在About.js中:
进一步智能化,直接获取到path:【适合更加复杂的项目路由】
Prompt组件 提示确认组件
例如,在表单中添加:
更加细化:防止用户误操作导致跳转页面之后原本页面输入的内容发生丢失。
Redirect组件 -- history的变种
作用就是页面的重定向。
其实相当于,原本是跳转到了/about路径下,但是由于使用了redirect,相当于replace,将about替换为form路径。但是!
如果我们使用了push来进行页面跳转,每当回退的时候,就会存在死循环,导致一直是form页面无法回退。
应用:用户登录之后才能访问的页面
添加一个state;
做判断;