你可能不知道的React-Router

前言

一不小心想起来了账号密码, 就写点什么吧。

这一年多也是经历了裁员 -> gap year -> 找工作 -> 找到工作还没找到工作,从最开始的玩的不亦乐乎,到后面的找工作怀疑人生,只能说一手烂牌,打的更是稀烂。正好最近面试有被问到React Router的实现,其实好久没看过源码了,所以面试回来又去简单看了下。

前端路由

前端路由一般分为 hash 路由和 history 路由两种模式,hash 模式下监听 hashchange 事件,history 模式监听 popstate 事件 ,从而渲染匹配对应的视图。所以我们会认为 React-Router 大概的逻辑也会是这样,大部分的博客文章里也是这么写的,我们面试也是这么回答的。

的确,在 React-Router v6 之前的版本也确实是这么做的,但是在 React-Router v6 或者是更高的 v6.4版本中,还是有些变化和区别的,这里说的区别主要是指对于 hash 模式下的事件监听。

popstate

Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event will be triggered by doing a browser action such as a click on the back or forward button (or calling history.back() or history.forward() in JavaScript).

Mdn 上 popstate 说点击了前进或者后退,或者调用了 history.back()history.forward() 会触发 popstate, 而 history.pushState()history.replaceState() 是不会触发 popstate 事件的。

其实 修改 hash 也是会触发 popstate 事件的,可以把下面的代码在控制台里跑一下。

javascript 复制代码
window.addEventListener('hashchange', function(){
    console.log('hashchange fired!')
});

window.addEventListener('popstate', function(){
    console.log('popstate fired!')
});

location.hash = 'foo'

这是因为 location.hash 修改了 hash,也会导致 history 对象的修改,

The popstate event of the Window interface is fired when the active history entry changes while the user navigates the session history. It changes the current history entry to that of the last page the user visited or, if history.pushState() has been used to add a history entry to the history stack, that history entry is used instead.

mdn 定义 history 对象的修改就会触发 popstate 事件,所以这个流程也能说得通,但是在 IE 浏览器下 修改 hash 无法触发 popstate

graph LR hash改变 --> history改变 --> 触发popstate

history

history 是一个单独的包,也是 React-Router 的依赖,React-Router 借助其实现不同模式的路由包括 hash 路由、history 路由、还有用于 React Native 的 memory 路由。

在 history v5 版本之前,hash 路由都是采用监听 hashchange 事件,history 监听 popstate 事件,就像我们开头说的那样。

然而在 v5 版本之后,选择使用 popstate + hashchange 双管齐下的方式去监听 hash 路由,其实最初也是没加 hashchange事件的,但是有人提了 bug 发现不兼容 IE11,所以在 IE 下特别处理了。

React-Router v6/v6+

React-Router v6.4以下还是保持了对 history 包 v5 版本的引用,就像上面所说的,v5 版本的 history 已经用 popstate 去监听 hash路由了,但是单独对不兼容的 IE 做了处理

React-Router v6.4开始,移除了对 history 包的依赖,选择自己在内部重写了一遍(把原来 history 包的代码 CV 大法过来加以修改),在6.4版本当中,React-Router 就已经完全舍弃了 hashchange 事件,不管是 hash 路由还是 history 路由,都用 popstate 来监听事件。意味着就算你使用 React-Router 创建了 hash 路由,React-Router 也是利用 popstate 去监听你的 url 变化。这也同时意味着如果你使用 React-Router 6.4之后的版本,就无法兼容 IE。

总结

  • 修改 hash 也会触发 popstate 事件,除了 IE 浏览器。
  • 抛开兼容性,就像 React18 说的不再支持 IE, 微软本身也官宣不再维护 IE,所以现代开发也可以基于 History api 去实现 hash 路由。
  • React-Router v6 完全基于 History api 去实现 hash 路由,不仅仅是 popstate 代替 hashchange 事件去监听,内部 hash 路由的跳转修改也是直接调用的 history.pushState/replaceState 相关 api。
相关推荐
撸猫7916 分钟前
HttpSession 的运行原理
前端·后端·cookie·httpsession
亦世凡华、24 分钟前
Rollup入门与进阶:为现代Web应用构建超小的打包文件
前端·经验分享·rollup·配置项目·前端分享
Bl_a_ck1 小时前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
chenyuhao20242 小时前
链表的面试题4之合并有序链表
数据结构·链表·面试·c#
augenstern4162 小时前
webpack重构优化
前端·webpack·重构
海拥✘2 小时前
CodeBuddy终极测评:中国版Cursor的开发革命(含安装指南+HTML游戏实战)
前端·游戏·html
寧笙(Lycode)2 小时前
React系列——HOC高阶组件的封装与使用
前端·react.js·前端框架
asqq82 小时前
CSS 中的 ::before 和 ::after 伪元素
前端·css
拖孩3 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
Hejjon3 小时前
Vue2 elementUI 二次封装命令式表单弹框组件
前端·vue.js