你可能不知道的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。
相关推荐
Danny_FD2 分钟前
前端BFC详解:从基础到深入的全面解读
前端
临枫38811 分钟前
网页图像优化:现代格式与响应式技巧
前端
咪库咪库咪22 分钟前
构建交互网站
前端
周星星日记23 分钟前
10.vue3中组件实现原理(上)
前端·vue.js·面试
小华同学ai24 分钟前
6.4K star!轻松搞定专业领域大模型推理,这个知识增强框架绝了!
前端·github
专业抄代码选手26 分钟前
【VUE】在vue中,Watcher与Dep的关系
前端·面试
Lazy_zheng30 分钟前
从 DOM 监听到 Canvas 绘制:一套完整的水印实现方案
前端·javascript·面试
尘寰ya32 分钟前
前端面试-微前端
前端·面试·职场和发展
蘑菇头爱平底锅33 分钟前
数字孪生-DTS-孪创城市-前端实现动态地铁分布线路图
前端·javascript·数据可视化
祯民37 分钟前
AI 时代前端进阶:10分钟入门基于 HuggingFace Transformers 库开源模型私有化部署
前端·aigc