你可能不知道的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。
相关推荐
cs_dn_Jie26 分钟前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic1 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿1 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具2 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161772 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test3 小时前
js下载excel示例demo
前端·javascript·excel
Yaml43 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事3 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶3 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo3 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx