找回密码
 立即注册
首页 业界区 业界 React Router 的实现原理

React Router 的实现原理

辉伫 3 天前
  本文分两部分,一说前端路由的基本原理,二说 React Router 的实现原理前端路由的基本原理​

不说屁话,从时间线上讲,Web 应用原本是后端渲染,后来随着技术的发展,有了单页面应用,慢慢从后端渲染发展成前端渲染
在博客前端路由hash、history的实现 一问中我已经介绍过这两种模式
hash 模式

  • 通过监听 hashchange 事件,匹配 hash 值并渲染页面模块
history 模式

  • 利用 history.pushState + popState 实现
  • history.pushState 能实现不刷新页面,但往历史栈中新增一个记录
  • popState 则会在历史记录条目被更改时,触发
  • pushState 只会改变历史栈,修改它没有什么API可以监听,所以要与 popState配合
简单来说,前端路由的基本原理无非要实现两个功能:

  • 监听记录路由变化
  • 匹配路由变化并渲染内容
hash模式​

hash 模式的实现比较简单,我们通过 hashChange 事件就能直接监听到路由 hash 的变化,并根据匹配到的 hash 的不同来渲染不同的内容。
  1. <body>
  2.     Home
  3.     User
  4.     About
  5.    
  6.   </body>
  7.   
复制代码
history模式​


  • 拦截 a 标签的点击事件,阻止它的默认跳转行为
  • 使用 H5 的 history API 更新 URL
  • 监听和匹配路由改变以更新页面
利用 pushState 往历史栈中添加记录且不刷新页面的特性 + 监听 popstate 浏览器操作导致的 URL 变化

  • window.history.pushState(state, title, path)
  • window.addEventListener("popstate", onPopState)
    1. <body>
    2.     Home
    3.     User
    4.     About
    5.    
    6. </body>
    复制代码
hash模式 VS History模式​

模式优点缺点Hash浏览器兼容性更好,不需要后端路由支持有 # 号History需要现代浏览器,需要后端路由支持无 # 号
history 模式下当页面刷新时,因为找不到相对应的路由(因为只有一个页面,路由由前端控制),所以会报404错误,需要在 Nginx(或者服务器)中配置,如果找不到ur,则返回 首页
nginx
  1. location / {
  2.     try_files $uri $uri/ /index.html;
  3. }
复制代码
React Router 的实现原理​

先用最简单的话来概括一下 React Router 到底做了什么?
本质上, React Router 就是在页面 URL 发生变化的时候,通过我们写的 path 去匹配,然后渲染对应的组件。
那么,我们想一下如何分步骤实现:

  • 如何监听 url 的变化 ?
  • 如何匹配 path ?
  • 渲染对应的组件
换句话说,也是一个组件,通过渲染不同的组件来控制路由切换
整体设计​

我们用一张图来理解一下整个 react-router 是怎么实现的:
接下来我们看看每一个步骤是怎么实现的。
1.png

如何监听 url 的变化 ?​

正常情况下,当 URL 发生变化时,浏览器会像服务端发送请求,但使用以下 3 种办法不会向服务端发送请求:

  • 基于 ajax(实现起来很麻烦)
  • 基于 hash
  • 基于 history
react-router 使用了 history 这个核心库。它本质是屏蔽不同模式下载监听实现上的差异,使用发布订阅模式 来实现,这里不做探究
总结​

从后端路由到前端路由,最大的改变是体验,体验更良好了
前端路由模式有两种:hash 模式 和 history 模式,两者分别利用浏览器自由特性实现单页面导航

  • hash 模式:window.location 或 a 标签改变锚点值,window.hashchange() 监听锚点变化
  • history 模式:history.pushState()、history.replaceState() 定义目标路由,window.popstate() 监听浏览器操作导致的 URL 变化
React Router 匹配路由由 mathPath 通过 path-to-regexp 进行, 相当于一个高阶组件,以不同的优先级和匹配模式渲染匹配到的子组件
React Router 的主要组件源码,整体的实现:

  • 对于监听功能的实现,React Router 引入了 history 库,以屏蔽了不同模式路由在监听实现上的差异, 并将路由信息以 context 的形式,传递给被  包裹的组件, 使所有被包裹在其中的路由组件都能感知到路由的变化, 并接收到路由信息
  • 在匹配的部分, React Router 引入了 path-to-regexp 来拼接路径正则以实现不同模式的匹配,路由组件·作为一个高阶组件包裹业务组件, 通过比较当前路由信息和传入的 path,以不同的优先级来渲染对应组件
参考资料​


  • 深入浅出解析 React Router 源码
  • 单页面应用路由实现原理:以 React-Router 为例
  • 剖析单页面应用路由实现原理
  • SPA 路由三部曲之核心原理
  • SPA 路由三部曲之实战演练
  • 图解 React-router 带你深入理解路由本质

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册