前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React Router源码浅析

React Router源码浅析

作者头像
LamHo
发布2022-09-26 10:42:40
1.1K0
发布2022-09-26 10:42:40
举报
文章被收录于专栏:小前端看世界小前端看世界

2020年的春节是一个多灾多难的春节,新型冠状病毒的出现折磨着每一个中国人的心,导致不少公司都安排节后在家办公,但是在这个时候,作为一名小前端也是要继续努力学习,所哟2020年的第一篇文章就从React Router的源码阅读开始,继续了解React的体系。


前言

为什么去看React Router的源码?

  • 了解React Router的实现原理
  • 如何监听路有变化以及渲染对应的组件

我一直认为,会用框架和用好框架是有很大的区别的,当用框架到一定程度的时候,就需要看看框架对应生态中那些不可获取的库,这样能加深在不同框架中同样的功能的优秀实现方案。

React Router是什么?

React Router是React团队开发的基于React框架架构所实现的路由库。

Github

React Router有多个版本。

一般前端写web页面多数是使用react-router-dom这个库,那么react-router和react-router-dom有什么区别呢?

其实react-router-dom是基于react-router再封装的一个带有React DOM组件的库,其中包括了Link、HashRouter、BrowserRouter等组件提供给开发者通过使用标签的方式控制路由跳转。


阅读须知

  • 源码阅读基于react-router和react-router-dom 5.2.1版本

React Router如何监听路由变化的?

通过查看源码发现,react-router使用了一个history的库来监听不同的路由变化,react-router支持我们使用hash和bowser两种路由规则,所以history这个库可以根据调用的api不同,来区分当前是监听不同的路由方式。

history

history这个库的内容并不在本文章的阅读范围内,有兴趣的可以自行查看。

我们开始逐步开始阅读源码。我们使用React Router的时候第一个了解的就是BrowserRouter和HashRouter这两个内置的组件。通过源码发现其实两个组件的实现是完全一样的,只是内部调用创建history实例的方式不一样,一个调用createHashHistory,另一个调用createBrowserHistory。

基于一个官方demo展开阅读:

代码语言:javascript
复制
export default class App extends React.Component {


    render () {
        return (
            <Router>
                <div>
                    <ul>
                        <li>
                            <Link to="/">Home</Link>
                        </li>
                        <li>
                            <Link to="/about">About</Link>
                        </li>
                        <li>
                            <Link to="/dashboard">Dashboard</Link>
                        </li>
                    </ul>
                    <hr />
                    <Route exact path="/">
                        <Home />
                    </Route>
                    <Route path="/about">
                        <About />
                    </Route>
                    <Route path="/dashboard">
                        <Dashboard />
                    </Route>
                </div>
            </Router>
        );
    }

}

BrowserRouter.jsx

HashRouter.jsx

本篇文章是基于HashRouter进行阅读,实际上只是监听的事件不一样而已。

通过源码发现,HashRouter实例化了一个history的实例,并且将history实例通过props和children一起传入的Router组件当中。

接下来是Router组件。

computeRootMatch函数中,如果pathname !== "/"的下,isExact会为false,后续会用到

Route组件

接下来我们看看matchPath函数是如何判断当前的url是否命中当前Route组件的path的。

到这里,就是大概整体渲染的时候React Router做了什么事情。

总结:

  1. HashRouter
    1. 实例化history,调用createHashHistory
    2. 将children和history传入Router组件
  2. Router
    1. constructor周期内监听history的路由事件,将新的location存到Router的state中
    2. componentWillUnmount移除监听
    3. 使用Context包裹子组件(Provider),存入history、location、match(默认的命中对象)等。
  3. Route
    1. 使用Context,声明为Consumer,接收Router传入的值。
    2. 调用matchPath函数来判断当前Route的path是否命中当前url。
    3. 使用Context包裹子组件(Provider),将Router传递进来的参数以及命中结果等传入给Route包裹的子组件
    4. 渲染循序如下:
      1. 当前Route是否命中url
          1. 判断当前Route是否有子组件,有那么将渲染子组件,否则进入下一条
          2. 判断当前Route是否有component参数,有就执行React.createElement创建component,否则进入下一条
          3. 判断当前Route是否有render参数(函数),有就执行render函数,否则进入下一条。
          4. 返回null
          1. 返回null

当我们的路由发生变化时,Router中所监听的history函数将会触发,返回新的location对象,这是将会触发Router的setState,然后对应所有绑定Router的Route都将会重新渲染判断是否命中路由来进行重新渲染。

Switch组件

如果我们只是单纯的使用Route组件来设置路由,当我们的当前的url满足多条路由规则的情况下,会出现多个Route的子组件进行渲染,这个时候如果当我们使用Switch包裹多个Route组件的话,那么只会渲染首先命中当前url的Route组件,具体是如何实现的呢?

所以Switch和Route的区别是在于,Switch只会渲染满足的条件的Route,而Route会根据传入的path来判断如果满足当前url的情况下,就会渲染Route的子组件。Switch就是从而实现Route同时只会命中一个的功能。

Link组件

Link组件也是相当简单的一个组件,内部主要做了以下事情:

  1. 判断传入参数replace,是使用replace还是push进行跳转
  2. 执行传入的onClick事件
  3. 判断一些参数,例如(传入_blank参数,将交由浏览器处理)
  4. 触发内部点击事件,使用history库实例后的push或replace来控制前端路由跳转
  5. 禁止默认事件

以下是Link组件的点击处理逻辑:

Link组件是如何获取到history的那,我们使用的时候并没有传递进去当前的history实例呀,实际上还记得之前看Route组件的时候,在return的时候,又包裹了一层Context吗,其实实际上就是给Link这类型的标签方便获取到history实例的,而Link组件也是使用Context。

结语

React Router的代码其实很好理解,主要涉及到的是history这个库是核心点,整个路由的触发事件的封装,抹平了浏览器差异。其次就是React Router实际是基于context来实现Router、Route、Link等组件中,history,location等值的传递。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • React Router是什么?
  • 阅读须知
  • React Router如何监听路由变化的?
  • Switch组件
  • Link组件
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档