vue react路由底层原理 | Hash & histroy 模式

一、前端路由原理

1. SPA(单页面应用)

单页面应用(Single Page Application)是一种只加载一次 HTML 页面并在用户与应用交互时动态更新页面内容的 Web 应用。浏览器在首次加载时会获取所需的 HTML、CSS 和 JavaScript 文件,之后所有的操作都通过 JavaScript 控制。这种模式非常适合现代 Web 应用,因为它可以提供流畅的用户体验。

我们结合 react 项目来理解就是 index.html 页面提供挂载点和 js 的引用

2. 路由的必要性

对于复杂的 SPA 应用,路由是不可或缺的。路由允许开发者在不同的页面之间切换,而无需重新加载整个页面。Vue 和 React 都提供了强大的路由功能,无论React 还是 Vue 的 router 都支持两种模式:Hash 模式和 History 模式。

我们先来看看 Hash 和 histroy 的核心差异

二、Hash 模式

1. 定义

Hash 模式是一种通过在 URL 中添加 # 符号来实现前端路由的方式。浏览器在检测到 # 后的路径变化时,不会重新发起请求,而是触发 onhashchange 事件。

2. 网页 URL 组成部分

  • location.protocol:协议(如 http:
  • location.hostname:主机名(如 127.0.0.1
  • location.host:主机(如 127.0.0.1:8001
  • location.port:端口号(如 8001
  • location.pathname:访问页面(如 01-hash.html
  • location.search:搜索内容(如 ?a=100&b=20
  • location.hash:哈希值(如 #/aaa/bbb

3. Hash 的特点

  • 无刷新跳转:Hash 变化不会触发页面刷新,因此不会重新加载资源。
  • 浏览器兼容性:Hash 模式兼容性较好,几乎所有现代浏览器都支持。
  • SEO 限制:Hash 模式下的 URL 不会被搜索引擎爬虫完全解析,因此不利于 SEO。
  • 灵活性 :Hash 模式只能修改 # 后面的部分,因此只能跳转到同文档的 URL。

4. Hash 模式的应用场景

  • To B 系统:企业内部系统通常对 SEO 要求不高,Hash 模式简单易用,适合快速开发。
  • 小型项目:对于功能简单的项目,Hash 模式可以快速实现路由功能。

5. 案例与代码示例

以下是一个简单的 Hash 模式实现:

javascript 复制代码
// 监听 hash 变化
window.addEventListener('hashchange', function() {
  console.log('Hash changed to:', location.hash);
  // 根据 hash 值加载对应的内容
  loadContent(location.hash);
});

// 初始加载
window.addEventListener('load', function() {
  console.log('Initial hash:', location.hash);
  loadContent(location.hash);
});

function loadContent(hash) {
  // 根据 hash 值加载内容
  if (hash === '#/home') {
    console.log('Loading home page...');
  } else if (hash === '#/about') {
    console.log('Loading about page...');
  } else {
    console.log('Loading default page...');
  }
}

三、History 模式

1. 定义

History 模式是 HTML5 提供的新特性,允许开发者直接更改前端路由,更新浏览器 URL 地址而不重新发起请求。

2. 与 Hash 模式的区别

通过一个例子来说明 Hash 和 History 模式在浏览器刷新时的区别:

  • 正常页面浏览
    • https://github.com/xxx 刷新页面
    • https://github.com/xxx/yyy 刷新页面
    • https://github.com/xxx/yyy/zzz 刷新页面
  • History 模式
    • https://github.com/xxx 刷新页面
    • https://github.com/xxx/yyy 前端跳转,不刷新页面
    • https://github.com/xxx/yyy/zzz 前端跳转,不刷新页面

3. History 的 API

  • history.pushState(data, title [, url]):向历史记录堆栈顶部添加一条记录。
  • history.replaceState(data, title [, url]):更改当前的历史记录。
  • history.state:存储 pushStatereplaceState 的数据。
  • window.onpopstate:响应 pushStatereplaceState 的调用。

4. History 的特点

  • 无刷新跳转 :通过 pushStatereplaceState 实现无刷新跳转。
  • SEO 友好:URL 更加规范,适合搜索引擎爬虫解析。
  • 服务端支持:需要服务端配置,否则刷新页面会导致 404 错误。

5. History 模式的应用场景

  • To C 系统:面向用户的系统通常对 SEO 要求较高,History 模式更适合。
  • 大型项目:功能复杂的项目需要更灵活的路由管理,History 模式可以提供更好的用户体验。

6. 案例与代码示例

以下是一个简单的 History 模式实现:

javascript 复制代码
// 使用 pushState 添加历史记录
function navigateTo(url) {
  history.pushState({}, '', url);
  loadContent(url);
}

// 监听 popstate 事件
window.addEventListener('popstate', function() {
  loadContent(location.pathname);
});

function loadContent(path) {
  // 根据路径加载内容
  if (path === '/home') {
    console.log('Loading home page...');
  } else if (path === '/about') {
    console.log('Loading about page...');
  } else {
    console.log('Loading default page...');
  }
}

// 初始加载
loadContent(location.pathname);

7. 服务端配置示例(Nginx)

为了支持 History 模式,需要在服务端配置中确保所有路由都指向主页面:

nginx 复制代码
server {
  listen 80;
  server_name example.com;

  location / {
    try_files $uri /index.html;
  }
}

四、两者的选择

在实际项目中,选择 Hash 模式还是 History 模式需要根据具体需求和场景来决定:

  • To B 系统:推荐使用 Hash 模式,因为它相对简单,且对 URL 规范不敏感。
  • To C 系统:可以考虑使用 History 模式,但需要服务端支持。
  • 成本与收益:能用简单的解决方案就不要用复杂的,尽量平衡开发成本和用户体验。

五、性能优化与最佳实践

1. 性能优化

  • 减少不必要的渲染:通过路由守卫或懒加载减少不必要的组件渲染。
  • 缓存策略:合理使用缓存策略,减少网络请求。
  • 代码分割:将路由相关的代码进行分割,按需加载。

2. 最佳实践

  • 统一的路由管理:使用路由库(如 Vue Router 或 React Router)统一管理路由。
  • 路由验证:在路由切换时进行权限验证,确保用户只能访问授权的页面。
  • 错误处理:捕获路由切换时的错误,提供友好的错误提示。

六、总结

Hash 和 History 模式各有优缺点,了解它们的区别和适用场景是前端开发中的重要技能。本文对前端路由原理进行了深入探讨,希望能为大家提供一些帮助。通过合理选择和优化,可以为用户提供一个流畅且高效的用户体验。

参考资料

相关推荐
阿珊和她的猫3 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
PAK向日葵5 小时前
【算法导论】PDD 0817笔试题题解
算法·面试
加班是不可能的,除非双倍日工资7 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi7 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip8 小时前
vite和webpack打包结构控制
前端·javascript
excel8 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国9 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼9 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy9 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT9 小时前
promise & async await总结
前端