JS-彻底搞懂“页面刷新”与“路由跳转”:单页应用(SPA)的灵魂所在

0 阅读4分钟

前言

很多刚接触 Vue 或 React 的同学经常会问:为什么我点击了导航栏,URL 变了,内容也变了,但浏览器顶部的刷新图标却没有转圈?这就是前端路由跳转原生页面刷新的本质区别。

一、 核心概念定义

1. 刷新页面(Page Refresh)

这是浏览器的原生行为。它会销毁当前整个页面的上下文,重新向服务器请求 HTML 文件,并依次加载 CSS、JS 等所有资源。

  • 关键词:重置状态、资源重载、白屏闪烁。

2. 路由跳转(Router Navigation)

特指单页应用(SPA)中的导航。它通过 JavaScript 监听 URL 变化,并动态替换 DOM 中的组件,而不重新请求页面

  • 关键词:局部更新、状态保留、无缝衔接。

二、 深度对比:跳转 vs 刷新

为了方便记忆,我们将两者在不同维度的表现总结如下:

1. 技术实现维度

维度路由跳转 (SPA)页面刷新 (Native)
底层机制基于 History API (pushState) 或 Hash浏览器底层指令 (如 location.reload)
URL 变化动态修改路径,不触发请求触发完整的 HTTP 请求周期
JS 执行持续运行,内存数据不丢失进程重启,变量全被清空

2. 用户体验维度

维度路由跳转 (SPA)页面刷新 (Native)
视觉感受瞬间切换,仅局部视图更新明显的白屏间隙,所有资源重新渲染
状态保留保留滚动位置、输入框内容、Vuex/Redux 状态丢失所有状态,回到初始加载状态
加载速度极快(仅请求少量的 JSON 数据或按需组件)较慢(需解析 HTML、下载全量静态资源)

三、 资源加载逻辑图解

在路由跳转中,浏览器就像是一个换衣间,只换衣服(组件),人(页面框架)不动;而在页面刷新中,则是拆房重建

维度路由跳转 (SPA)页面刷新 (Native)
资源请求不需要额外请求,仅需加载当前视图的异步组件(如 Vue 懒加载)全量请求:HTML、CSS、JS 等资源重新加载
服务器压力低(仅首次加载入口文件时会加载较多资源)高(频繁刷新增加服务器负载)
缓存利用充分利用浏览器缓存可能因缓存策略导致旧资源加载(需 ?t=timestamp 强制更新)

四、 进阶:如何实现“不刷新”的跳转?

面试中常问: “前端路由跳转是如何做到改变 URL 却不刷新页面的?”

主要依靠以下两种方案:

  1. Hash 模式:改变 URL 中 # 之后的部分。浏览器不会向服务器发请求,但会触发 hashchange 事件。
  2. History 模式:使用 HTML5 的 history.pushState(state, title, url)。它能修改浏览器的历史堆栈并改变地址栏,但不会触发页面刷新

五、 面试模拟题

Q1:单页应用(SPA)中,路由跳转后点击浏览器的“后退”键会发生刷新吗?

参考回答:

不会。路由库(如 Vue Router)会监听 popstate 事件,捕获到用户的后退操作后,依然通过 JavaScript 动态切换组件,从而维持“不刷新”的体验。

Q2:为什么有些场景下我们必须使用“刷新”而不是“跳转”?

参考回答:

  1. 版本更新:当部署了新的前端代码,需要用户清空旧的 JS 缓存时,通常需要强制刷新。
  2. 内存清理:如果页面长时间运行产生了严重的内存泄漏,通过 location.reload() 可以彻底释放内存。
  3. 第三方脚本重置:某些老旧的第三方库可能不支持单页环境下的多次初始化,必须通过刷新来重置其内部状态。

Q3:History 模式路由在生产环境下,刷新页面会出现 404,为什么?如何解决?

参考回答:

  • 原因:路由跳转是 JS 模拟的。当你直接在地址栏刷新 /user/profile 时,浏览器会真向服务器请求这个文件。但服务器上其实只有 index.html,没有 profile 这个文件夹,所以返回 404。
  • 解决:在 Nginx 或后端服务器上做回退配置(Fallback) ,将所有路径的请求都重定向到 index.html,然后交给前端路由来接管解析。