前言

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

这一年多也是经历了裁员 -> 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 callinghistory.pushState()orhistory.replaceState()won’t trigger apopstateevent. Thepopstateevent will be triggered by doing a browser action such as a click on the back or forward button (or callinghistory.back()orhistory.forward()in JavaScript).

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

其实 修正 hash 也是会触发 popstate 事情的,能够把下面的代码在控制台里跑一下。

window.addEventListener('hashchange', function(){
    console.log('hashchange fired!')
});
window.addEventListener('popstate', function(){
    console.log('popstate fired!')
});
location.hash = 'foo'

这是由于 location.hash 修正了 hash,也会导致 history 目标的修正,

你或许不知道的React-Router

Thepopstateevent of theWindowinterface 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, ifhistory.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。