写在前面:由于源码比较简单,就没有贴上分析的源代码,有感兴趣的可以查看文章最后面的 React-Mini-Router 的实现,大概 5 分钟就能理解最基础的实现了。

react-router 原理

react-router 本质是 url 发生改变不需要和后端进行交互,也就是通常所说的单页应用,不需要刷新浏览器,纯粹浏览器发生的一系列行为,url 变更完全由自己处理 dom 的变化;

hash 路由

  • 特征是 url 后面会有 # 号;
  • 通过 locaiton.hash = ‘#a/b/c’ 去改变hash路由;
  • window.addEventListener(‘hashchange’,() => 监听 hash 变化);

history 路由

  • 通过 window.history.pushState(state,title,url) 去改变 url;
  • window.addEventListener(‘popstate’, () => 只能监听到浏览器前进和后退的变化) ;

    ⚠️ qiankun 使用的 single-spa.js 中会通过 window.dispatchEvent(new PopStateEvent(“popstate”, {})) 重写 window.history.pushState 方法,这时 window.addEventListener(‘popstate’, () => 可以监听所有的行为);

  • 所以需要单独的一个库实现 history 的功能,实现 push,replace 等 api,有自己的 linsters 监听回调;
  • qiankun 中使用有坑,子页面路由切换不刷新,原因是主应用 window.history.pushState 在子应用重新 mount 即 Router 加载之前,history 保存的还是上一次的 location 信息;

Router 实现方式

  1. 依赖 history 作为路由的管理;
  2. 监听 history 的刷新状态;
  3. 使用 Context.Provider 设置 value = {history} , Switch 和 Route 组件就是消费者了 ;

Switch 实现方式

  1. 使用 Context.Provider 获得最新的 history.location 信息;
  2. 利用 location.pathname 和 children.key 匹配需要显示哪个子组件(path-to-regexp 做动态路由匹配);
  3. 匹配到单个符合规则的路由的 Route 结束匹配;

Route 实现

  1. 如果上层没有被的 switch 包裹着,可能会匹配到多个 Router (取决于 exact);
  2. 渲染匹配到组件,通过 Context.Provider 传递 props(history)信息给组件;

总结:

1. 什么是 React 路由?

是开发 React App 单页应用的一个强大路由库,保障 url 和页面 ui 信息能够同步渲染,他有一套标准化的路由结构和行为。

2. V4版本中为什么使用 Switch ?

Switch 可以按照顺序匹配到符合的 Route 组件,从而绕过其他的线路。

4. 为什么需要 Router?

Router 是顶层API,可用于定义多个路由,url 可以与 Router 之内定义的多个 Route 匹配,url 变化时能同步渲染匹配到的组件,

5. React 路由的优点?

  1. 基于 React 组件开发;
  2. V4 版本中使用 BrowserRouter 无需自己设置历史记录;
  3. 提供 web,native,core 三个包,支持跨平台;

6. React 路由和传统路由的区别?

区别 React 路由 传统路由
视图 单个组件 整个页面
服务端交互 每次变更不与服务端交互,仅更新历史记录 每次变更需要重新与服务端交互
体验 局部刷新 刷新整个页面

附上代码:实现 React-Mini-Router