浏览器回退时是否会重新加载相关问题
Q:在传统多页应用(MPA)中页面回退是否会重新加载?
A:在传统MPA
中(不做任何处理和优化的情况下),只要是发生路由变化,都会被视为页面跳转,如index.html -> index2.html or index2.html->index.html
以及window.histry.back() or window.histry.go(-1)
都会出现页面的重新加载,因为现象上看到的就是从页面A到页面B,自然就需要加载对应的页面内容;
Q:在现代单页应用(SPA)中页面回退是否会重新加载?
A:在现代SPA
中本身不存在页面的跳转,只是路由变化,所以只要是在当前页面内的路由变化,本质上是不会触发浏览器的重新加载的,window.histry.back() or window.histry.go(-1)
也都一样,只是触发了路由变化而已
Q:那为什么在SPA中我返回上一页时会看到页面组件重新加载,并且重新发起请求呢?
A:常见的情况有比如说列表页现在在第4页时,跳转详情,返回后又回到了第一页并在控制台能看到重新发起了页面相关请求,这是因为我们的路由配置原因; 如下代码配置了我们应用各个路由所需要加载的组件,匹配到对应路由时则会渲染对应的组件,所以在路由变化时,就会执行组件卸载/组件加载,故而出现页面内容刷新的情况,但左侧菜单栏、顶部信息栏等不跟随路由变化而变化,所以全局只会加载一次不会出现重复加载的情况
<RouterControl locationTo={location} isOpen={isOpen} routeList={routeList} setDismissLogin={setDismissLogin}>
<Layout routeList={routeList} isOpen={isOpen || !!matchQuery(location.search, 'source')}>
<Suspense fallback={<Spin />}>
<TransitionGroup component={null}>
<CSSTransition key={location.pathname} classNames='fade' timeout={300}>
{/* https://juejin.cn/post/6844903922574819342#heading-7 */}
<Routes location={location}>
{routeList.map((item) => (
<Route key={item.path} path={item.path} element={<item.component location={location} />}></Route>
))}
{/* 匹配找不到的路由 */}
<Route path='*' element={<NotFound />}></Route>
</Routes>
</CSSTransition>
</TransitionGroup>
</Suspense>
</Layout>
</RouterControl>
Q:那我们要怎么合理的解释这一个情况呢?
A:这就需要结合react-router
原理来说了;和react-router
相关联的有两个库,分别是react-router-dom & history.js
,在开发中我们通常不会直接依赖react-router
、histroy.js
,而是把所有API、组件从react-router-dom
导出使用,它们的关系如下图
-
react-router
实现了router
的最核心能力。提供了Router
、Route
等组件,以及配套方法、hook
。 -
react-router-dom
则是react-router
在浏览器下的更上一层封装。把浏览器history api
传入Router
并初始化成BrowserRouter
、HashRouter
,补充了Link
这样给浏览器直接用的组件。同时把react-router
透传导出,减少开发者依赖。 -
history.js
给browser
、hash
两种history
统一了 api,补充了订阅的能力,最终规范成react-router
需要的接口供react-router-dom
调用。- 核心能够让SPA不刷新就改变浏览器地址的就是通过这个第三方库来实现的
- 这个库同时劫持了浏览器的前进后退事件,具体如何实现就不在这赘述了,可以自行查阅 github地址