一个路由就是一个映射关系(key:value),key为路由路径, value可能是function/component。
就是对浏览器的地址栏进行监测,当发现地址栏的地址发生变化,会根据地址的路由路径去匹配相对应的组件,并在展示区域展示。
在react项目使用 react-router-dom 来控制路由,这个插件是专门为web网页使用的。
react-router-dom V5
- 现在最新的版本是 V6
- 下载指定版本需要指定版本号
- 在项目中想要使用路由对整个页面的控制,也就是能够监听全局所有的改变路由地址的操作,同时能够根据路由地址变化去渲染不同的组件,这是就需要将整个项目的根组件包裹在路由中
- 所以一般可以在项目的入口文件中在挂载 App 组件使使用路由再包裹一层
- 路由模式有两种:BrowserRouter 和 HashRouter
- 路由匹配模式默认为模糊匹配
// index.js 项目入口文件
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router} from 'react-router-dom' // 这里使用改名引入,这样后期需要更改路由模式时就直接修改这里即可
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Router>
<App />
</Router>
);
react-router-dom插件中的组件
-
<BrowserRouter><HashRouter>- 这两个组件决定了项目的路由模式,使用方式是在项目的入口文件将根组件包裹在挂载到指定容器中
-
<Route>- 使用语法:
<Route path='想要匹配的路径' component={想要加载的组件}> - 当页面路由改变就会跟Route中的path匹配,匹配成功则渲染component绑定的组件
- 想要加载的组件只需要写引入时定义的变量即可,不需要使用 <> 包裹
- 而当前的组件称之为路由组件
- 路由组件的 props 接收到三个固定属性:history、location、match
- 使用语法:
-
<Link><NavLink>- link 和 NavLink 的使用相同,都可以修改路由地址
- 语法:
<link to='指定一个路由地址'></link><NavLink to='指定一个路由地址'></NavLink> - link 不会根据当前的路由地址,对自己进行一个高亮提示。而 NavLink 却相反
- NavLink 还可以通过给属性 activeClassName 传入一个class名,这样就可以自定义高亮的样式
- 以上连接跳转默认是 push 方式跳转,可以添加属性 replace ,可以让当前的路由不被记录
-
<Switch>- 用来包裹组件 Route 列表
- 使用 Switch 包裹的路由列表在匹配的时候会在匹配成功后就终止匹配,后面的路由组件就不会再去匹配
- 这样可以提高效率,减少计算
-
<Redirect>- 重定向路由
- 语法:
<Redirect to="指定一个路由地址" /> - 用于在路由组件列表的底部使用,当前面的路由组件都没有匹配上时,就跳转到Redirect指定的路由地址
// 举例
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Redirect to="/about"/>
</Switch>
路由嵌套
- 在路由组件中继续嵌套路由时,需要注意将所有的父级路由路径写完整,才可以展示完整的路由组件
// 父级路由
<Route path='/home' component={home}>
// 在home的组件中再嵌套路由, 下面是举例在组件中
<NavLink to="/home/new"></NavLink> // 这里 to 的地址一定要把所有父级路由依照嵌套关系写,有多层就写多级
<Route path="/home/new" component={home}> // 这里匹配的 path 也是一样
向路由组件传递参数
- params 参数传递
- 路由连接携带参数:
<NavLink to="/home/new/18"></NavLink> - 注册路由时接收参数:
<Route path="/home/new/:id" component={home}> - 路由组件中通过:this.peops.match.params 获取参数
- 路由连接携带参数:
- search 参数传递
- 路由连接携带参数:
<NavLink to="/home/new/?id=18&title=你好"></NavLink> - 注册路由时无需接收参数
<Route path="/demo/test" component={Test}/> - 路由组件中通过:this.props.location.search
- 备注:获取到的search是urlencoded编码字符串,需要借助querystring插件解析,这个插件脚手架已经帮我们下载好了
- 路由连接携带参数:
// 路由组件中引入 querystring
import qs from 'querystring'
const search = qs.parse(this.props.location.search.slice(1))
// 因为 search 参数是一串字符串,且字符串前带有?,所以先截取,再通过 qs 转义为对象
- state参数
- 路由链接(携带参数):
<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link> - 注册路由(无需声明,正常注册即可):
<Route path="/demo/test" component={Test}/> - 接收参数:this.props.location.state
- 备注:刷新也可以保留住已传递的参数
- 路由链接(携带参数):
编程式导航
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
- this.prosp.history.push('跳转地址', state) 向页面栈添加当前页面记录,再跳转到下一个页面
- this.prosp.history.replace('跳转地址', state) 页面栈不保留当前页面记录,直接跳转到下一个页面
- 上面的跳转方式,第二个参数为可选参数,传递的是state参数。其他参数传递编写在地址中
- this.prosp.history.goBack() 后退
- this.prosp.history.goForward() 前进
- this.prosp.history.go(n) n 为正整数时则前进 n 步,n为负整数则后退 n 步
withRouter
- withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
- withRouter的返回值是一个新组件
// 在一个组件内 引入
import { withRouter } from 'react-router-dom'
class Header extends Component{}
// 暴露的时候
export default withRouter(Header)
BrowserRouter与HashRouter的区别
- 底层原理不一样:
- BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
- HashRouter使用的是URL的哈希值。
- path表现形式不一样
- BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
- HashRouter的路径包含#,例如:localhost:3000/#/demo/test
- 刷新后对路由state参数的影响
- .BrowserRouter没有任何影响,因为state保存在history对象中。
- .HashRouter刷新后会导致路由state参数的丢失!!!
- 备注:HashRouter可以用于解决一些路径错误相关的问题。