react 路由详细讲解
Posted 地中海真帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react 路由详细讲解相关的知识,希望对你有一定的参考价值。
介绍:
今天学习了react的重点知识路由,这个知识点是react中的一大块,大家有兴趣的话可以跟随作者的文章继续学习呦
SPA介绍:
单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的 Web 应用。它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的html、javascript 和 CSS。一旦页面加载完成了,SPA不会因为用户的操作而进行页面的重新加载或跳转。取而代之的是利用 JavaScript 动态的变换HTML的内容,从而实现UI与用户的交互。由于避免了页面的重新加载,SPA 可以提供较为流畅的用户体验。
优缺点
单页Web程序的出现是富客户端发展的必然结果,但是该技术也是有些局限性,所以采用之前需要了解清楚它的优缺点。
优点:
-
良好的交互体验
-
良好的前后端工作分离模式
-
减轻服务器压力
-
共用一套后端程序代码
缺点:
-
SEO难度较高
-
前进、后退管理
-
初次加载耗时多
路由的理解
① 什么是路由?
当应用变得复杂的时候,就需要分块的进行处理和展示,传统模式下,我们是把整个应用分成了多个页面,然后通过 URL 进行连接。但是这种方式也有一些问题,每次切换页面都需要重新发送所有请求和渲染整个页面,不止性能上会有影响,同时也会导致整个 JavaScript 重新执行,丢失状态。
安装
npm i -S react-router-dom
② 路由分类
- 后端路由
理解: value是function, 用来处理客户端提交的请求。
注册路由: router.get(path, function(req, res))
工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
- 前端路由
浏览器端路由,value是component,用于展示页面内容。
注册路由:
工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
react-router-dom
安装命令
cnpm install react-router-dom -S
npm install react-router-dom -S
下载到生产环境的依赖中。
在组件中通过对象的解构方式去获取到react-router-dom内置组件,在组件中,按需引入内置组件,在页面中进行使用:
HashRouter表示一个路由的根容器,将来所有的路由相关的东西,都要包裹在HashRouter里面,而且一个网站中,只需要使用一次HashRouter就好了;
Route表示一个路由规则,在Route上,有两个比较重要的属性,path,component
Link表示一个路由的链接,属性to
import {HashRouter,Route,Link} from 'react-router-dom'
路由的基本使用
-
明确好界面中的导航区、展示区
-
导航区的a标签改为Link标签
<Link to="/xxxxx">Demo</Link>
- 展示区写Route标签进行路径的匹配
<Route path='/xxxx' component={Demo}/>
-
<App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>
ReactDOM.render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.getElementById('root')
)
一般组件:
路由组件:
- 存放位置不同:
一般组件:components
路由组件:pages
接收到的props不同:
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性
//路由属性打印结果展示
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location:
pathname: "/about"
search: ""
state: undefined
match:
params: { }
path: "/about"
url: "/about"
- NavLink使用与封装
NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
- Switch的使用
1.通常情况下,path和component是一一对应的关系。
2.Switch可以提高路由匹配效率(单一匹配) ---- 即匹配到一个后将不再往下匹配
6、解决多级路径刷新页面样式丢失的问题
-
public/index.html 中 引入样式时不写 ./ 写 / (常用)
-
public/index.html 中 引入样式时不写 ./ 写 %PUBLIC_URL% (常用,但只在react中有效果)
-
使用HashRouter (不常用)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>react脚手架</title>
<!-- 方法二 -->
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- 方法一 -->
<link rel="stylesheet" href="/css/bootstrap.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
- 路由的严格匹配与模糊匹配
默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
开启严格匹配:<Route exact={true}path="/about" component={About}/>
可以省略exact={true}为exact
注意:
严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
//编写路由链接
About
Home
{/* 注册路由 */}
<Switch>
<Route exact path="/about" component={About}/>
<Route exact path="/home" component={Home}/>
</Switch>
- Redirect的使用
一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
具体编码:
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Redirect to="/about"/>
</Switch>
9、嵌套路由
注册子路由时要写上父路由的path值
路由的匹配是按照注册路由的顺序进行的
-------------------注册一级路由-----------------------------
{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
{/* 注册路由 */}
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Redirect to="/about"/>
</Switch>
----------------------注册二级路由 :Home组件-----------------------------------
<div>
<ul className="nav nav-tabs">
<li>
<MyNavLink to="/home/news">News</MyNavLink>
</li>
<li>
<MyNavLink to="/home/message">Message</MyNavLink>
</li>
</ul>
{/* 注册路由 */}
<Switch>
<Route path="/home/news" component={News}/>
<Route path="/home/message" component={Message}/>
<Redirect to="/home/news"/>
</Switch>
</div>
- 向路由组件传递参数
路由参数
- history : 历史记录以及路由给我们的一些操作
- location : 获取当前URL的一些信息
- pathname : 当前的URL
- search : 接口参数
- state : 跳转路由时,传递的参数
- match : 当前路由匹配的相关规则
- params : 动态路由传过来的参数
Ⅰ-params参数
路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
注册路由(声明接收):
接收参数:this.props.match.params
-------------------------------发送参数:父组件----------------------------------------------
<div>
{/* 向路由组件传递params参数 */}
<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
<hr />
{/* 声明接收params参数 */}
<Route path="/home/message/detail/:id/:title" component={Detail} />
</div>
--------------------------------接受参数:子组件-----------------------------------------------------------
const {id,title} = this.props.match.params
Ⅱ-search参数
路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
-------------------------------发送参数:父组件----------------------------------------------
<div>
{/* 向路由组件传递search参数 */}
<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
<hr />
{/* search参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
</div>
--------------------------------接受参数:子组件-----------------------------------------------------------
import qs from 'querystring'
// 接收search参数
const {search} = this.props.location
const {id,title} = qs.parse(search.slice(1))
Ⅲ-state参数
路由链接(携带参数):[<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>]
注册路由(无需声明,正常注册即可):[<Route path="/demo/test" component={Test}/>]
接收参数:this.props.location.state
注意:
-
使用BrowserRouter刷新才可以保留住参数,使用HashRouter刷新后state将会没有history来保存参数
-
子组件接受参数时const {id,title} = this.props.location.state || {} ,后面添加||{}是防止使用HashRouter后state为undefined时报错
-------------------------------发送参数:父组件----------------------------------------------
<div>
{/* 向路由组件传递state参数 */}
<Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link>
<hr />
{/* state参数无需声明接收,正常注册路由即可 */}
<Route path="/home/message/detail" component={Detail}/>
</div>
--------------------------------接受参数:子组件-----------------------------------------------------------
// 接收state参数,后面添加`||{}`是防止使用`HashRouter`后state为undefined时报错
const {id,title} = this.props.location.state || {}
11、编程式路由导航
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
-
-this.prosp.history.push()
跳转到指定路径的页面 -
-this.props.history.replace()
替代栈位置,即不会产生历史记录 -
-this.props.history.goBack()
回退一格 -
-this.props.history.goForward()
前进一格 -
-this.props.history.go()
前进或者后退n格(根据传入的数字正负数)
withrouter
解决一般组件中使用路由组件特有的api,withrouter加工完后是一个新组件
3. Hooks
1. React Hook/Hooks是什么?
(1). Hook是React 16.8.0版本增加的新特性/新语法
(2). 可以让你在函数组件中使用 state 以及其他的 React 特性
2. 三个常用的Hook
(1). State Hook: React.useState()
(2). Effect Hook: React.useEffect()
(3). Ref Hook: React.useRef()
3. State Hook
(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)
(3). useState()说明:
参数: 第一次初始化指定的值在内部作缓存
返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
4. Effect Hook
(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
(2). React中的副作用操作:
发ajax请求数据获取
设置订阅 / 启动定时器
手动更改真实DOM
(3). 语法和说明:
useEffect(() => {
// 在此可以执行任何带副作用操作
return () => { // 在组件卸载前执行
// 在此做一些收尾工作, 比如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
(4). 可以把 useEffect Hook 看做如下三个函数的组合
componentDidMount()
componentDidUpdate()
componentWillUnmount()
5. Ref Hook
(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样
总结:
今天学习了react的核心路由,路由覆盖的知识点非常全面,也比较复杂,初学者会比较容易犯错,大家一定要小心各个知识点的注意事项,react的路由和vue的路由也是有些许相似的,如果有vue基础的话,会更加易学一些,最后希望大家对每个知识点都多加练习,在练习中逐渐掌握```
最后作者创作不易,如果文章对你有帮助的话,记得留下你的点赞呃关注呦
以上是关于react 路由详细讲解的主要内容,如果未能解决你的问题,请参考以下文章
使用具有不同片段字段的相同中继根查询的多个 react-router-relay 路由