React-Router
前端路由规则
URL的hash
URL的hash也就是锚点(#), 本质上是改变window.location的href属性- 我们可以直接赋值
location.hash改变url, 但是页面不发生刷新
const routerView1 = document.querySelector('.router-view')
window.addEventListener('hashchange', () => {
switch (window.location.hash) {
case '#/home':
routerView1.innerHTML = '首页';
break;
case '#/about':
routerView1.innerHTML = '关于页';
break;
default:
routerView1.innerHTML = '';
break;
}
})
注意:
hash的优势就是兼容性更好, 在老版,IE中都可以运行- 但是缺陷是有一个#, 显得不像一个真实的路径
HTML5的history
- history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面:
| API | 作用 |
|---|---|
| replaceState | 替换原来的路径 |
| pushState | 使用新的路径 |
| popState | 路径的回退 |
| go | 向前或向后改变路径 |
| forward | 向前改变路径 |
| back | 向后改变路径 |
react-router
react-router介绍及安装
- React Router的版本4开始,路由不再集中在一个包中进行管理了
react-router是router的核心部分代码;react-router-dom是用于浏览器的;react-router-native是用于原生应用的;
- 目前我们使用最新的
React Router版本是v5的版本:- 实际上
v4的版本和v5的版本差异并不大;
- 实际上
- 安装
react-router:- 安装
react-router-dom会自动帮助我们安装react-router的依赖; yarn add react-router-dom
- 安装
Router的基本使用
react-router最主要的API是给我们提供的一些「组件」
BrowserRouter或HashRouter组件Router中包含了对路径改变的监听, 并且会将相应的路径传递给子组件BrowserRouter使用了history模式HasRouter使用了hash模式
Link组件和NavLink组件- 通常路径的跳转时是使用
Link, 最终会被渲染成a元素 NavLink是在Link基础之上增加了一些样式属性(后续学习)to属性:link组件中最重要的属性, 用于设置跳转到的路径
- 通常路径的跳转时是使用
Route组件- 「Route用于路径的匹配」
path属性: 用户设置匹配到的路径component属性: 设置匹配到的路径后, 渲染的组件exact属性: 精准匹配, 只有精准匹配到完全一致的路径, 才会渲染对应的组件
// ...
import { BrowserRouter, Link, Route } from 'react-router-dom'
export default class App extends PureComponent {
render() {
return (
<div>
<BrowserRouter>
<Link to="/">主页</Link>
<Link to="/about">关于</Link>
<Link to="/profile">我的</Link>
{/*添加exact属性: 精准匹配*/}
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
</BrowserRouter>
</div>
)
}
}
NavLink组件的使用
- 需求:「路径选中时,对应的a元素变为红色」
- 这个时候,我们要使用
NavLink组件来替代Link组件activeStyle: 活跃时(匹配时)的样式activeClassName: 活跃时添加的calssexact: 是否精准匹配
{/* NavLink的使用,需求:路径选中时,对应的a元素变为红色 */}
<NavLink exact to="/"
activeClassName="link-active">
主页
</NavLink>
<NavLink
to="/about"
activeStyle={{ color: 'red', fontSize: '35px' }}>
关于
</NavLink>
Switch组件的使用
- 使用场景: 只要有一个
path匹配上了对应的组件, 后续就不会再进行匹配了 - 我们来看下面的路由规则:
- 当我们匹配到某一个路径时,我们会发现有一些问题
- 比如
/about路径匹配到的同时,/:userid也被匹配到了,并且最后的一个NoMatch组件总是被匹配到
- 原因是什么呢?默认情况下,
react-router中只要是路径被匹配到的Route对应的组件「都会被渲染」- 但是实际开发中, 我们希望有一种排他的思想
- 只要匹配到了第一个, 后面就不应该继续匹配了
- 这个时候我们可以使用
Switch来将所有Route组件进行包裹
Redirect 重定向
- Redirect用于路由的重定向, 当这个组件出现后, 就会执行跳转对应的
to路径中
<Redirect to="/login" />
react-router其他补充
路由的嵌套
手动路由跳转 withRouter
❝目前我们实现的跳转主要是通过
❞Link或者NavLink进行跳转的,实际上我们也可以通过「JavaScript」代码进行跳转
- 获取
history对象- 方式一: 如果该组件是「通过路由直接跳转过来」的, 可以直接从
props属性中获取history, location, match - 方式二:App组件中获取到
history对象,需要使用whitRouter**高阶组件 **App组件必须包裹在BrowserRouter或HashRouter组件之内App组件使用withRouter高阶组件包裹
- 方式一: 如果该组件是「通过路由直接跳转过来」的, 可以直接从
// 1.不使用Link组件或NavLink组件实现跳转
joinTo() {
// 1.使用的history是通过Route组件传递的props
// 2.通过Route传递的history对象来实现路径的跳转
this.props.history.push('/about/join')
}
// app.js
jumpToProduct() {
this.props.history.push('/product')
}
参数传递
「传递参数有三种方式:」
- 动态路由的方式;
- search传递参数;
- Link中to传入对象
动态路由传递参数:
比如我们将
path在Route匹配时写成/detail/:id,那么/detail/abc、/detail/123都可以匹配到该Route,并且进行显示图示
// App.js
<NavLink to={`/detail/${id}`}>详情</NavLink>
<Route path="/detail/:id" component={Detail} />
// Detail.js
{/* 获取动态路由传递的 id 参数 */}
<h2>Detail: {match.params.id}</h2>
search传递参数
在
Link或NavLink组件通过to属性传递query string图示
Link中 to 属性可以直接传入一个对象
// app.js
<NavLink
to={{
pathname: "/detail",
search: "?name=abc",
state: info
}}
>进入详情</NavLink>
// detail.js
console.log(this.props.location)
react-router-config
react-router-config基本配置
目前我们所有的路由定义都是直接使用
Route组件,并且添加属性来完成的 但是这样的方式会让路由变得非常混乱
- 将所有的路由配置放到一个地方进行集中管理
- 使用:
react-router-config来完成
- 使用:
- 安装
react-router-configyarn add react-router-config- 配置路由映射关系数组
const routes = [
{ path: '/', component: Home, exact: true },
{ path: '/profile', component: Profile },
{ path: '/detail/:id', component: Detail },
]
// app.js
import { renderRoutes } from 'react-router-config'
import routes from './router'
render() {
// ...
{ renderRoutes(routes) }
}
// about.js
嵌套子路由配置映射关系
- 在路由嵌套中配置路由映射关系
const routes = [
{
path: '/about',
component: About,
route: [
{
path: '/about',
component: AboutHistory,
exact: true
},
{
path: '/about/join',
component: AboutJoin,
},
]
}
]
// about.js ( 在被Route渲染的组件中: 使用props取出route )
render() {
{ renderRoutes(this.props.route.route) }
}