React-Router源码解读

🤔 问题背景

目前保险业务用的是react技术栈,在开发过程中遇到了两个路由相关的奇怪问题:
【示例代码】

1⃣️.【问题1】在使用React—Router的basename功能的时候发现,无论是使用 HashRouter 还是 BrowserRouter,路由中有没有basename都能够匹配到对应的组件,哪怕我们已经给路由加上了 exact 即严格匹配规则.
在这里插入图片描述

2⃣️.【问题2】 在排查 【问题1👆】 的时候发现在浏览器的 Console 中对hash进行修改能正常切换页面,但是用history修改url却不会. 然而在代码中使用history API(history.push)修改路由却又是可以的😵 (猜测是react-router重写了history的API).

更改hash能正确切换路由
在这里插入图片描述

在这里插入图片描述
使用history.pushState不能切换路由
在这里插入图片描述

上面2个问题涉及到了【React-Router是如何匹配对应路径组件】,【React如何重写window.history API】 以及 【window.history API内部逻辑】等等问题. 所以我就借着解决上面两个问题的想法去了解了一下React-Router的源码。在下面讲解文章的过程中,顺带解释一下业务中遇到的问题以及原因.

😺 React-Router

React-router的源码同学们可以在 https://github.com/ReactTraining/react-router 下载.

项目结构

打开下载好的React-Router项目,如下图所示,可以看到最最核心部分是packages文件下的四个文件夹,分别是 react-routerreact-router-configreact-router-domreact-router-native,这个四个文件夹每个都可以作为单独的包进行发布,但是React把它们都放在一个仓库中,是一种典型的 monorepo 代码组织方式. 👉 什么是monorepo

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4uj5H3sQ-1606383072060)(https://tech-proxy.bytedance.net/tos/images/1606039968376_09d31d2c64771171ffb45c244e3acb07.png)]

  • 那这四个文件夹分别有什么用呢?
  • react-router:是React-Router的核心库,处理一些共用的逻辑.
  • react-router-config:是React-Router的配置处理,我们一般不需要使用
  • react-router-dom:浏览器上使用的库,会引用react-router核心库.
  • react-router-native:支持React-Native的路由库,也会引用react-router核心库.
    从上面的解释来看对于我们前端H5开发的同学来说最重要的就是 react-router
    react-router-dom 这两个文件了.
  • 打开 react-router-dom 根文件index.js
    可以看到除了BrowserRouter,HashRouter,Link以及NavLink这四个组件是react-router-dom自己独立实现的,其他的(比如最基础的Router,Route,Switch组件等等)都来自react-router里的公用组件.
export {
  MemoryRouter,
  Prompt,
  Redirect,
  Route,
  Router,
  StaticRouter,
  Switch,
  generatePath,
  matchPath,
  withRouter,
  useHistory,
  useLocation,
  useParams,
  useRouteMatch
} from "react-router";

export { default as BrowserRouter } from "./BrowserRouter.js";
export { default as HashRouter } from "./HashRouter.js";
export { default as Link } from "./Link.js";
export { default as NavLink } from "./NavLink.js";

HashRouter & BrowserRouter

先来个简单的demo:

import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom"

function App() {
   return (
      <Router>
        <div>主菜单</div>
        <Link to="/home">home</Link>
        <br />
        <Link to="/search">search</Link>
        <hr />
        <Switch> 
          <Route path="/home" component={Home}  />
          <Route path="/search" component={Search} />
        </Switch>
      </Router>
      )
}

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

可以看到,HashRouter/BrowserRouter 是所有组件Switch、Route、Link等组件的父组件,也是一个根组件,所以我们以它作为入口看下它实现了一些什么功能:

  • HashRouter
import { createHashHistory as createHistory } from "history";
class HashRouter extends React.Component {
  history = createHistory(this.props);
  render() {
    return <Router history={this.history} children={this.props.children} />;
  }
}
export default HashRouter;
  • BrowserRouter
// 与HashRouter唯一的区别在这里,引入的是createBrowserHistory
// 而不是HashHistory
import { createBrowserHistory as createHistory } from "history";
class BrowserRouter extends React.Component {
  history = createHistory(this.props);
  render() {
    return <Router history={this.hi
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值