ReactRouter基础
本质上react-router有三个模块,react-router、react-router-dom、react-router-native
在React项目中,路由实现需要使用react-router-dom
模块
react-router安装/使用
# npm
npm i --save react-router-dom
# yarn
yarn add react-router-dom
我们需要在我们的项目中引入react-router-dom
import {
BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'
BrowserRouter/HashRouter
如果我们要使用路由,那么应该在App.js中用BrowserRouter包着所有的代码
前者路由url中不带#,后者带#
BrowserRouter基于HTML5的pushState操作,HashRouter基于hash操作
一个页面只会有一个Router
import {
BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'
function App () {
return (
<div className="app">
<Router>
</Router>
</div>
)
}
Route
每一个路由都放在一个Route里
ute path="路由路径">
<Component a={
1}></Component>
</Route>
<!-- 第二种写法 -->
<Route path="路由路径" component={
组件}></Route>
<!-- 第三种写法 -->
<Route path="路由路径" render={
(props) => <Component {
...props} a={
1}></Component>}></Route>
</Router>
上面的三种方式区别在于组件内部的props的内容
function Page (props) {
// 第一种方式 props中只能获取到我们添加到组件上的自定义属性
// 第二种方式 props中包含了所有的路由信息 不包含自定义属性,也无法设置
// 第三种方式 porps默认为空,可以添加自定义属性,如果想要有路由信息,需要我们设置对应props传递
return (
<div></div>
)
}
exact
精确匹配,如果不添加该属性 path=“/” 也会匹配到 /xxx
,可以给Route添加该属性
<Route exact></Route>
Switch
如果Route的path和url匹配,则对应的Route的组件就会渲染,Switch控制了Route只能渲染匹配到的第一个。
<Router>
<Switch>
<Route path="路由路径">
<Component></Component>
</Route>
<!-- 第二种写法 -->
<Route path="路由路径" component={
组件}></Route>
<!-- 第三种写法 -->
<Route path="路由路径" render={
() => <Component></Component>}></Route>
</Switch>
</Router>
Link
会被渲染成a标签,和vue的router-link相同
<Link to="path">链接名称</Link>
NavLink
和Link的区别在于NavLink会根据当前URL匹配对应的a标签添加类名 active
<NavLink to="path">链接名称</NavLink>
路由配置
如果想要像vue一样实现路由的配置,我们可以自己写配置,并根据配置渲染出对应的路由结构
安装 react-router-dom
npm install react-router-dom -S
// 或者
yarn add react-router-dom
配置好routes
const routes = [
// 同级重定向
{
path: "/redirect",
render: () => <Redirect to="/demo1"/>
},
{
path: "/",
exact: true,
component: Index
}, {
path: "/demo1",
component: Demo1,
// 子路由配置
routes: [
{
path: "/demo1/child1",
component: Child1
},
// 重定向 父 -> 子
{
path: "/demo1",
render: () => <Redirect to="/demo1/child1"/>
}
]
}
]
在App.js中添加函数
import {
BrowserRouter as Router } from 'react-router-dom'
import {
renderRoutes } from 'react-router-config'
import routes from '路由配置路径'
function App () {
return (
<div className="App">
<Router>
{
renderRoutes(routes)}
</Router>
</div>
)
}
找到有子路由的组件
import {
renderRoutes } from 'react-router-config'
function 组件名 ({
route}) {
return (
<div>
{
renderRoutes(route.routes)}
</div>
)
}
组件懒加载
组件的配置
组件需要放在lazy中调用
FuntionComponent.js
function FuctionComponent () {
return (
<div>组件</div>
)
}
export default FunctionComponent
懒加载
import {
Lazy } from 'react'
const FunctionComponent = Lazy(() => import('组件路径'))
把通过Lazy引入的组件放在对应的组件中
Suspense组件可以去包裹Lazy加载的组件,内部可以包裹多个
<Suspense fallback={
<div>loading...</div>}>
<Lazy组件></Lazy组件>
</Suspense>
在组件外使用路由导航功能
假如我们需要在组件外使用history进行路由导航。比如:在响应拦截器中遇到token失效跳转登录页的场景
安装模块react-router和history
yarn add react-router history
到App.js进行结构改造
App.sj
import './App.css';
// import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom'
import {
Route, Switch, Redirect} from 'react-router-dom'
// 从上一步安装的模块中,引入对应的Router
import {
Router } from 'react-router'
// 引入创建history对象方法
import {
createBrowserHistory } from 'history'
import Login from './views/Login';
import MainLayout from './views/Layout';
import NotFound from './views/NotFound';
// 创建history对象 并且导出 在需要进行导航的地方引入并调用方法即可
export const history = createBrowserHistory()
function App() {
return (
<div className="App">
{
/* 把创建的history对象添加到Router上 */}
<Router history={
history}>
...
</Router>
</div>
);
}
export default App;