依赖包

  • react-router:提供了 router 的核心 api。如 Router、Route、Switch 等,但没有提供有关 dom 操作进行路由跳转的 api;
  • react-router-dom:提供了 BrowserRouter、Route、Link 等 api,可以通过 dom 操作触发事件控制路由。

安装 react-router

因为 react-router-dom 有 react-router 的依赖,所以就可以这样安装

1
npm install -S/-save react-router-dom

路由的模式有两种:

  • 老浏览器提供的 hash 模式, 我们称之为: HashRouter
  • H5 提供的的 history 模式,我们称之为 BrowserRouter (注意: H5 模式的路由需要后端支持)

使用路由

1
2
3
4
5
6
7
8
import { BrowserRouter } from "react-router-dom";

ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);

路由的展示区域
书写路由展示区域, 使用 Route path 是路径 component 是组件

  • 第一种写法
1
<Route path="/Home" component={home}></Route>
  • 第二种写法
1
<Route path = "/Home" render={(props)=>{return <Home />}></Route>
  • 第一种写法路由上会自己自动加上路由元信息,而第二种需要手动的去在 render 函数上加上路由元信息

路由的重定向

  • 第一种方式
1
<Redirect to="/" component={Home} />
  • 第二种方式
1
<Redirect from="/" to="/home" />

路径完全匹配 exact/

1
<Route to="/" component={Home} exact />

Switch ( 路由只匹配一次 )

1
2
3
4
5
6
7
<Switch>
<Route path="/" component={Home} exact></Route>
<Route path="/home" component={Home}></Route>
<Route path="/mine" component={Mine}></Route>
<Route path="/mine/login" component={Login} exact></Route>
<Route path="/list" component={List}></Route>
</Switch>

NavLink( 路由激活时可以用 activeClassName 来添加 active 类名 )

1
2
3
<NavLink activeClassName="active" className="nav-link" to="/home">
Home
</NavLink>

Link
Link 组件用于取代元素,生成一个链接,允许用户点击后跳转到另一个路由。它基本上就是元素的 React 版本,可以接收 Router 的状态。

Home

NavLink 和 Link 的区别:
Link 使用 to 参数来描述需要定位的页面。它的值既可是字符串,也可以是 location 对象(包含 pathname、search、hash、与 state 属性)如果其值为字符串,将会被转换为 location 对象;replace(bool):为 true 时,点击链接后将使用新地址替换掉访问历史记录里面的原地址;为 false 时,点击链接后将在原有访问历史记录的基础上添加一个新的纪录。默认为 false;
的一个特定版本,会在匹配上当前的 url 的时候给已经渲染的元素添加参数,组件的属性有

  • activeClassName(string):设置选中样式,默认值为 active
  • activeStyle(object):当元素被选中时,为此元素添加样式
  • exact(bool):为 true 时,只有当导致和完全匹配 class 和 style 才会应用
  • strict(bool):为 true 时,在确定为位置是否与当前 URL 匹配时,将考虑位置 pathname 后的斜线
  • isActive(func)判断链接是否激活的额外逻辑的功能

路由

  • 路由的概念:随着浏览器地址栏的变化,展示给用户不同的界面(视图组件)
  • 路由模式:hash 模式(#) | history 模式
  • 路由应用场景:需要实现多页面跳转功能

react 项目中的路由

路由插件 react-router-dom 下载命令 :

1
npm install react-router-dom -S

路由插件的常见的内置组件

  • BrowerRouter 路由根组件
  • Redirect 路由重定向组件
  • Switch 避免路由重复匹配的组件,子项只能是 Redirect 或者 Route
  • Route 路由视图组件 加载路由
  • NavLink 路由跳转组件 自带高亮 active 类
  • Link 路由跳转 没有高亮

路由元信息 一般用路由视图组件 Route 加载的组件具备路由信息

  • history 路由跳转
  • location 获取一般路由传参
  • match 获取动态路由传参

高阶路由

  • 高阶路由包裹不具备路由元信息的组件可使其携带路由元信息

路由跳转

1
2
3
//引入路由内置组件
import { Link } from "react-router-dom";
<Link to="/del"> </Link>;

方式二 js 方式跳转 路又远信息 history 对象可以实现路由跳转

1
2
//注意使用js方式跳转 时  条件:当前组件必须具备路由元信息
this.props.history.push("/del");

路由传参

state 方式传参 页面刷新 参数依旧存在

1
2
3
4
5
6
7
8
9
//跳转传参
this.props.history.push({
pathname: "/del",
state: {
// 参 数
},
});
// 获取参数
this.props.location.state.obj;

query 传参 页面刷新参数不存在

1
2
3
4
5
6
7
8
9
//跳转传参
this.props.history.push({
pathname: "/路径",
query: {
obj: item,
},
});
//获取参数
this.props.location.query.obj;

动态路由传参

1
2
3
4
5
6
//1.设置锚点  形参
<Route path="/detail/:id" component-={Detail} />;
//2.路由跳转传参 实参
this.props.history.push(`/detail/$(item.id)`);
//3.获取动态路由传参
this.porps.match.params.id;

封装路由

  • 在项目的 src 目录下新建 router 文件夹,router 文件目录下新建 index.js 和 config.js
  • router/config.js —生成路由配置表,路由配置表=数组,每一个路由即一个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//引入一级路由视图组件
import Index from '../views/Index'
//引入二级路由
improt Home from '../views/index/Home'
const routes=[
{
path:'/',
redirect:'/index/home'
},
{
path:'/index',
component:Index,
children:[
{
path:'/index/home',
component:Home
}
]
}
}];
//抛出路由表
export default routes;
  • router/index.js 加载路由视图组件的函数组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//加载路由视图组件的函数组件 -条件-路由路径对应路由视图组件---对应的关系 ---》获取路由配置表
import React from 'react';
//引入路由内置组件
import {React,Redirect,Switch } from 'react-router-dom';
const RouterView =(props)=>{
let reds=props.routes.filter(e=>e.redirect);
let comS=props.routes.filter(e=>e.component);
return <Switch>
{
//渲染route视图组件
comS.map((item,index)=>{
return <Route key={index} path={item.path} render={(RouteProps)=>{
if(item.children){
return <item.component {...RouteProps} routes={item.children} />
}else{
return <item.component {...RouteProps} />
}
})} />
})
}
//渲染重定向
{
reds.map((item,index)=> {
return <Redirect to={item.redirect} />
})
}
</Switch>
}
  • 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { Component } from "react";
// 引入路由内置组件
import { BrowserRouter } from "react-router-dom";
// 引入加载路由视图得函数组件
import RouterView from "./router/index";
// 引入路由配置表
import config from "./router/config";
export default class App extends Component {
render() {
return (
<div className="App">
<BrowserRouter>
{/* 加载/展示路由视图组件 */}
<RouterView routes={config} />
</BrowserRouter>
</div>
);
}
}

路由拦截/路由守卫

  • i. 设置标识在需要路由守卫对象中设置标识
1
2
3
4
5
{
path:'/index/my',
component:'My',
autoLogin:true,//第一步设置标识
}
  • ii. 判断是否需要路由守卫 加载路由对象的时候判断是否需要路由守卫
1
2
3
4
5
6
//第二部 判断当前路由对象是否需要路由守卫
if(item.autoList){
//需要路由守卫
}esle{
//不需要路由守卫
}
  • iii. 判断是否登录 登录凭证 token
1
2
3
4
5
6
7
8
9
10
11
//第三步  判断当前登录状态 一登录 未登录 凭证token 本地存储
return localStorage.getItem("token") ? (
<item.component {...routeProps} {...itrm.children} />
) : (
<Redirect
to={{
pathname: "/login",
path: item.path,
}}
/>
);
  • iv. 获取 token 登录成功后 拿到 token ,跳转路由拦截之前的路由路径
1
2
3
4
//本地存储 token
localStorage.setItem("token", res.data.token);
//跳转兰姐之前的页面
this.props.history.push(this.props.location.path);

路由懒加载

方式一:React.lazy

fallback 属性接受任何在组件加载过程中你想展示的 React 元素。你可以将 Suspense 组件置于懒加载组件之上的任何位置。你甚至可以用一个 Suspense 组件包裹多个懒加载组件。
React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 default export 的 React 组件。
然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Suspense } from "react";
const OtherComponent = React.lazy(() => import("./OtherComponent"));
const AnotherComponent = React.lazy(() => import("./AnotherComponent"));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</div>
);
}

方式二:react-loadable (适用于 reactV16.8 以下)

下载插件:

1
yarn add react-loadable

使用:

1
2
3
4
5
6
7
8
import Loadable from "react-loadable";
function Loading() {
return <h3>正在加载..</h3>;
}
const LoadableComponent = Loadable({
loader: () => import("./my-component"),
loading: Loading,
});