这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」 简介
React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步。
原生js
这一部分其实也可以不用看,直接跳到下面。
原生中的六种路由跳转
大概又分为两类,一类操作的是window对象,另一类是history。 react-router操作的应该是history对象(可以跳到源码中看一看)
window.location.href = 'http://www.baidu.com';
window.loaction.hash = '#search' // 向网址后面追加 #serach
window.location.replace("http://www.baidu.com")
history.back()
history.go(-1)
history.pushState(null, null, '?path1');
history.pushState(null, null, '?path2');
导航栏
传统的
在不使用react或Vue这种脚手架框架之前。我之前写过的boostarp导航栏,左侧导航栏是要在每个文件中都写一次的。然后选中的那页的tab状态样式是选中的样式。这就是新的一页,而不是只改变中间的部分
或者,把中间内容作为一个iframe,去改变iframe的显示(当然现在也有这样做的,大部分微服务都是这么做的,因为多个系统共用一个导航栏)
react
而react有了组件的概念,根据路由匹配到相应的组件,并展示。
React Router
分类
react中的组件主要分为三类:
- 路由器
<BrowserRouter/>
和<HashRouter/>
- 路由匹配器,
<Route>
和<Switch>
(v6是<Routes>
) - 导航,
<link> <NavLink> <Redirect>
react-router-dom 和 react-router
react-router
: 实现了路由的核心功能\react-router-dom
: 基于react-router
,加入了在浏览器运行环境下的一些功能。例如:Link
组件,会渲染一个a
标签,Link组件源码a
标签行BrowserRouter
和HashRouter
组件,前者使用pushState
和popState
事件构建路由,后者使用window.location.hash
和hashchange
事件构建路由。
可以跳进去看下源码 index.js 和 index.d.ts
这里插曲一下index.d.ts:
为什么会有这个文件,我们要知道typescript要想运行需要转为js才行,这就导致一个问题:ts 那么多类型数据都没了,所以需要一个 d.ts 文件来标记某个 js 库里面对象的类型。
reac-router
这是 reac-router 导出的组件
export { MemoryRouter, Navigate, Outlet, Route, Router, Routes, LocationContext as
UNSAFE_LocationContext, NavigationContext as UNSAFE_NavigationContext, RouteContext
as UNSAFE_RouteContext, createRoutesFromChildren, generatePath, matchPath, matchRoutes
, renderMatches, resolvePath, useHref, useInRouterContext, useLocation, useMatch,
useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useRoutes };
react-router-dom
这是react-router-dom导入的内容,可以看出从它依赖于 reac-router、react及 history。
import { useRef, useState, useLayoutEffect, createElement, forwardRef, useCallback, useMemo } from 'react';
import { createBrowserHistory, createHashHistory, createPath } from 'history';
import { Router, useHref, useLocation, useResolvedPath, useNavigate } from 'react-router';
如下是它导出去的内容,这些都是针对浏览器的
export { BrowserRouter, HashRouter, Link, NavLink, createSearchParams,
useLinkClickHandler, useSearchParams };
路由器
对于Web项目而言,react-router-dom提供了<BrowserRouter>
和<HashRouter>
两个路由器。二者区别在于存储URL 和 与web服务器通讯方式。
- BrowserRouter 常规URL
- HashRouter 将当前位置存储在URL的哈希部分中,因此URL总会有个
#
井号,新建的项目大部分是使用这种路由器的。
既然是路由器,那么它们就需要写在路由的最外部,如下:
<BrowserRouter>
<Nav/>
<Routes>
<Route path="/" exact element={<Home/>} />
<Route path="/login" exact element={<Login/>} />
<Route path="/register" exact element={<Register/>} />
{/* <Route path="/register" exact component={Register} /> */}
</Routes>
</BrowserRouter>
路线匹配器
原本是有两个路线匹配组件<Switch>
和 <Route>
,但最近发布了v6版本,有些改动,
- 将
<Switch>
替换为<Routes>
(对了可以去源码中看v6版本没有了<Switch>
),并且从单词角度来看,<Route>
存在于<Routes>
更为合理。 <Route>
的传参
<Route path="/register" exact component={Register} />
<Route path="/" exact element={<Home/>} /> // 新版本 6.v
<Switch>
和<Routes>
渲染时 会搜索其子元素<Route>
,然后根据子元素的路径找到匹配的组件。找到后,它会渲染该<Route>
并忽略所有其他路由。如果没有匹配到,则<Switch>
和<Routes>
不渲染任何内容。
exact
<Route path>
,path匹配的是开头,而不是整个。比如/index
和/index/add
,当找匹配到 /index
之后就不会向下去匹配了。
而加了exact后就会精准匹配。
导航
Link
Link
组件用于取代<a>
元素,生成一个链接,允许用户点击后跳转到另一个路由。它基本上就是<a>
元素的React 版本,可以接收Router
的状态。
- to 替代了 href属性,接收跳转的路径
<Link to="/about">About</Link>
- 如果希望当前路由 样式与其他不同 使用activeStyle,直接在标签内添加样式
<Link to="/about" activeStyle={{color: 'red'}}>About</Link>
使用activeClassName 添加class
<Link to="/about" activeClassName="active">About</Link>
NavLink
是<Link>
的一种特殊类型,当其prop与当前位置匹配时,可以将其自身设置为“active”
Redirect
从现在的位置跳到另一个位置
<Route path="inbox" component={Inbox}>
{/* 从 /inbox/messages/:id 跳转到 /messages/:id */}
<Redirect from="messages/:id" to="/messages/:id" />
</Route>
history
React Router 是建立在 history 之上的。 简而言之,一个 history 知道如何去监听浏览器地址栏的变化, 并解析这个 URL 转化为 location
对象, 然后 router 使用它匹配到路由,最后正确地渲染对应的组件。
1.hashHistory
路由将通过URL的hash部分(#
)切换,URL的形式类似example.com/#/some/path
import { hashHistory } from 'react-router'
render(
<Router history={hashHistory} routes={routes} />,
document.getElementById('app')
)
2.browserHistory
如果设为browserHistory
,浏览器的路由就不再通过Hash
完成了,而显示正常的路径example.com/some/path
,背后调用的是浏览器的History API。
import { browserHistory } from 'react-router'
render(
<Router history={browserHistory} routes={routes} />,
document.getElementById('app')
)
3.createMemoryHistory
createMemoryHistory
主要用于服务器渲染。它创建一个内存中的history
对象,不与浏览器URL互动
const history = createMemoryHistory(location)