一、介绍
使用 React 构建的单页面应用,要想实现页面间的跳转, 想要随着 url 地址的改变切 换显示不同的内容,首先想到的就是使用路由。在 React 中,常用的有两个包可以实现 这个需求,那就是 react-router 和 react-router-dom。
react-router实现了路由的核心功能,而react-router-dom是基于 react-router,加入了在浏览器运行环境下的一些功能,例如: Link 组件,会渲染一个 a 标签, BrowserRouter 和 HashRouter 组件,前者使用 pushState 和 popState 事件构建路由,后者使用 window.location.hash 和 hashchange 事件构建路由。
二、路由的使用
1、安装路由库
npm i react-router-dom@5
2、相关组件
定义路由时,需要将对应的路由组件引入项目
例如
import Index from './views/Index'
路由管理组件
BrowserRouter , HashRouter , MemoryRouter , NativeRouter , StaticRouter Route, Link,NavLink,Switch,Redirect 这些是常用组件, 可以有选择的导入个别组件,所有路由组件必须包裹在路由管理组件内部。
常用的组件有BrowserRouter , HashRouter
BrowserRouter 使用 HTML5 历史记录 API(pushState,replaceState 和 popstate 事件)的来保持您的 UI 与 URL 同步。
HashRouter 使用 URL 的哈希部分(即 window.location.hash)的来保持您的 UI 与 URL 同步
路由组件
Switch <Switch>的所有子项应为<Route>或<Redirect>元素,渲染与位置匹配的第一个子元素<Route>或<Redirect>, <Switch>是独特的,因为它仅仅渲染一个路由。相反,与位置匹配的每个<Route>都会渲染。简单来说就是:Switch 包裹的路由规则,当从上往下匹配到某条路由规则时,会停止继续匹配其余的路由规则,自身用来定义路由规则,同时也充当占位组件
Route 元素尝试将其路径与当前历史记录位置(通常是当前浏览器 URL)进行 匹配,渲染与位置匹配的组件; 如果路由没有路径,将始终匹配;
Redirect 渲染将导航到新位置。新位置将覆盖历史堆栈中的当前位置;
Link 最终渲染成 a 标签
NavLink 最终渲染成 a 标签, 会自动维护 a 标签的 active 类的添加/移除( 当浏览 器地址栏的地址和哪个 a 标签的路由地址相匹配时, 该 a 标签会自动添加 active 类, 其他 不匹配的 a 标签会自动移除 active 类 ).
所有路由组件必须包裹在路由管理组件内部
例如:
<BrowserRouter>
<Route path=" / index" component={Index} />
</BrowserRouter>
整个应用只能写一个路由管理组件,放置在App组件的外面,Route组件本身就可以充当占位组件的角色(组件渲染出口),为了方便我们可以使用BrowserRouter包裹根组。
例如:
<BrowserRouter>
<App />
</ BrowserRouter>
二级路由
想要定义二级路由,需要在对应的一级路由组件中定义
3、懒加载
用以下形式加载的组件最终会打包成一个独立的js文件,只会在访问到该路由时对应的组件才会临时加载.
var Index = lazy(() => import('./views/Index'))
4、案例
定义一级路由
<BrowserRouter>
<Switch>
<Route exact path="/index" component={Index}/>
<Route exact path="/index" component={Index}/>
<Route exact path="/register" component={Register}/>
//重定向
<Redirect exact from='/' to="/index" />
//404页面
<Route path="*" component={NotFound}/>
</Switch>
</BrowserRouter>
定义二级路由
<Switch>
<Route exact path="/index/home" component={Home}/>
<Route exact path="/index/cate" component={cate} />
<Route exact path="/index/allgood" component={Al1good}/>
<Route exact path="/index/shopcart" component={Shopcart]/>
<Route exact path="/index/mine" component={Mine} />
<Redirect from='/index' to="/index/home"/>
<Route path="*" component={NotFound} />
</Switch>
声明式导航
Link会渲染成a标签,但是路由匹配成功时不会自动添加按钮的高亮类
NavLink会渲染成a标签,路由匹配成功时会自动添加按钮的高亮类
<NavLink to='/index/home'>首页</NavLink>
<NavLink to='/index/cate'>分类</NavLink>
<NavLink to='/index/allgood'>全部商品</NavLink>
<NavLink to='/index/car'>购物车</NavLink>
<NavLink to='/index/mine'>我的</NavLink>
编程式导航
通过 js 路由对象的方式实现路由的跳转叫做编程式导航, 主要用到以下三个路由对象: history, location, match
只有经过路由匹配渲染出来的组件,组件的props对象中才会出现history,location,match三个路由对象.
默认所有通过路由匹配渲染出来的组件,组件的props中都会自动添加history,location,match三个路由对象
其他不是通过路由匹配渲染出来的组件,props默认是空的.
history负责跳路由
location负责保存路由相关参数
match负责保存路由相关参数
跳路由的方法
this.props.history. push('');
this.props.history.go('');
this.props.history.goBack('');
this.props.history.goForward('');
this.props.history.repalce('');
注意:
被 Route 处理过之后或者用 withRouter 高阶组件处理过后才有这三个路由对 象! 个别非路由匹配渲染的组件没有路由对象, 这时用 withRouter 处理一下就可以了
import {NavLink, withRouter} from 'react-router-dom'
import "../styles/Tabbar.scss"
class Tabbar extends Component {…
}
//withRouter是个路由库提供的高阶组件,它可以给当前组件动态添加location,history,match是三个路由对象到props中.
export default withRouter(Tabbar);