1.一文读懂 react-router 原理
一文读懂 react-router 原理
react-router是源码react生态系统中关键的一部分,它帮助我们管理URL以及实现页面组件间的源码切换。本文将深入react-router源码,源码探究其工作原理。源码
在开发中,源码我们通常不会直接使用react-router的源码丝足 源码核心API,而是源码从react-router-dom中导出所有API和组件。此外,源码还有我们不直接接触的源码history库,它们共同构成了完整的源码router功能,它们之间的源码关系如下:
这就是三个关键模块间的关系。
react-router:基于Context的源码全局状态下发
router是一个“Provider-Consumer”模型,你在最外层提供一个Provider,源码在内部任意位置都可以用Consumer接到数据。源码显然,源码栏板源码这里使用了React.Context。
这里下发了两个Context:RouterContext、HistoryContext,都是隔壁模块导入的单例,所以一个项目中只能用一套react-router。那这两个有什么不同?各自下发了哪些状态?
RouterContext
RouterContext下发一个对象,主要包含三个信息:
其中,gitlib源码history来自history库提供的统一API,包括history的读取、操作、订阅等。
location来自Router的一个状态,Router会在mount的时候监听history,并在改变时更新location:
match用来描述当前Route对URL的lrp源码匹配信息。Router来自Class的静态方法,写死了根路由的信息。
HistoryContext
HistoryContext更简单,直接下发了history:value={ this.props.history}。但是HistoryContext为什么要单独给呢?
总结下来,Router的结构如下:
:路由递归
Route用来匹配路由,特性如下:
根据当前路由匹配规则渲染对应组件
首先Route要判断自己是ipps源码否匹配:
Route嵌套的实现
为了实现Route套Route,Route每次渲染都会重建一个RouterContext.Provider,把值更新为当前Route下计算后的router信息。
总结如下:
matchPath方法细节
最后打开matchPath方法看细节:
组件取值
组件可能需要哪些值?
可能通过哪些方式拿到?
消费Context的方式显然更通用,因此react-router的消费实现大多用这种方式。
withRouter()
在没hook前,withRouter是我们取route信息的主要方式。它是个简单的HOC:
hooks
有hook后,react-router提供了几个hook,也都是基于useContext来做的。
其他路由组件
react-router还提供了一些其他组件来丰富调用方式,举个的例子看看。
react-router-dom组件: 和
只是在用不同的history调:
history接口
主要几个信息:
实现思路
如图:
模块划分:
主要调用逻辑:
createBrowserHistory和createHashHistory的差异
两个方法向外暴露的接口完全一样,为了抹平差异,实现上做了如下两点适配:
1、location属性计算
createBrowserHistory下,location中的pathname, search, hash直接来自于window.location。
createHashHistory下则都是从#后的hash中解析出来的,比如hash部分是#/a/b?c=1#/d,解析出{ hash: '#/d', search: '?c=1', pathname: '/a/b'}。
2、event listener事件监听
createBrowserHistory只需监听popstate,而createHashHistory还要监听hashchange,而且这里要判断下前后location是否相等,因为hashchange可能是无效的。
小结