前端路由 Hash 和 History 模式原理对比区别

前端路由 Hash 和 History 模式原理对比区别

1. 基本概念

1.1 什么是前端路由

前端路由是指在单页应用(SPA)中,通过 JavaScript 来实现页面的切换和状态管理,而无需向服务器请求新的页面。主要有两种实现方式:Hash 模式和 History 模式。

1.2 为什么需要前端路由

  1. 提升用户体验:页面切换无需刷新,更流畅
  2. 减少服务器压力:无需每次都请求完整页面
  3. 实现前后端分离:前端负责路由,后端只提供数据
  4. 支持单页应用(SPA):整个应用只有一个 HTML 页面

2. Hash 模式

2.1 原理

Hash 模式是基于 URL 的 hash(即 URL 中的 # 号)来实现的。hash 值的改变不会导致浏览器向服务器发送请求,但会触发 hashchange 事件。

// 基本实现原理
class HashRouter {constructor() {// 存储路由映射this.routes = {};// 监听 hash 变化window.addEventListener('hashchange', this.handleHashChange.bind(this));// 初始化时也需要处理一次window.addEventListener('load', this.handleHashChange.bind(this));}// 注册路由register(path, callback) {this.routes[path] = callback;}// 处理 hash 变化handleHashChange() {// 获取当前 hash 值const hash = window.location.hash.slice(1) || '/';// 执行对应的回调函数const handler = this.routes[hash];if (handler) {handler();}}// 导航到指定路由push(path) {window.location.hash = path;}
}// 使用示例
const router = new HashRouter();router.register('/', () => {console.log('Home page');
});router.register('/about', () => {console.log('About page');
});// 导航到指定页面
router.push('/about');

2.2 特点

  1. 兼容性好

    • 支持所有浏览器,包括 IE
    • 无需服务器配置
  2. URL 格式

    http://example.com/#/path
    
  3. 实现机制

    • 基于 window.location.hash
    • 监听 hashchange 事件
  4. 服务器交互

    • hash 变化不会触发页面刷新
    • 不会向服务器发送请求

3. History 模式

3.1 原理

History 模式是基于 HTML5 History API 实现的,主要使用 pushState() 和 replaceState() 方法来改变 URL,并且不会触发页面刷新。

// 基本实现原理
class HistoryRouter {constructor() {this.routes = {};// 监听 popstate 事件window.addEventListener('popstate', this.handlePopState.bind(this));// 初始化时处理当前路由this.handlePopState();// 拦截所有 <a> 标签点击事件document.addEventListener('click', e => {const target = e.target;if (target.tagName === 'A') {e.preventDefault();this.push(target.pathname);}});}// 注册路由register(path, callback) {this.routes[path] = callback;}// 处理路由变化handlePopState() {const path = window.location.pathname;const handler = this.routes[path];if (handler) {handler();}}// 导航到指定路由push(path) {// 更新 URLhistory.pushState({}, '', path);// 手动触发路由处理this.handlePopState();}// 替换当前路由replace(path) {history.replaceState({}, '', path);this.handlePopState();}
}// 使用示例
const router = new HistoryRouter();router.register('/', () => {console.log('Home page');
});router.register('/about', () => {console.log('About page');
});// 导航到指定页面
router.push('/about');

3.2 特点

  1. URL 格式

    http://example.com/path
    
  2. 实现机制

    • 基于 HTML5 History API
    • 监听 popstate 事件
  3. 服务器配置

    • 需要服务器支持
    • 所有路由都指向同一个 HTML 文件
  4. API 支持

    // 添加新记录
    history.pushState(state, title, url)// 替换当前记录
    history.replaceState(state, title, url)// 前进/后退
    history.forward()
    history.back()
    history.go(n)
    

4. 两种模式的对比

4.1 实现原理对比

特性Hash 模式History 模式
URL 格式带 # 号无 # 号,更美观
实现原理hashchange 事件History API
服务器配置不需要需要配置支持
兼容性所有浏览器HTML5 浏览器

4.2 使用场景对比

  1. Hash 模式适用于

    • 需要兼容老浏览器
    • 无法修改服务器配置
    • 简单的单页应用
  2. History 模式适用于

    • 现代化的单页应用
    • 可以配置服务器
    • 需要更好的 URL 展示

5. 实际应用示例

5.1 Vue Router 配置

// Hash 模式
const router = new VueRouter({mode: 'hash',routes: [...]
});// History 模式
const router = new VueRouter({mode: 'history',routes: [...]
});

5.2 服务器配置

# Nginx 配置示例 (History 模式)
location / {try_files $uri $uri/ /index.html;
}
# Apache 配置示例 (History 模式)
<IfModule mod_rewrite.c>RewriteEngine OnRewriteBase /RewriteRule ^index\.html$ - [L]RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule . /index.html [L]
</IfModule>

6. 最佳实践建议

6.1 选择建议

  1. 使用 Hash 模式当

    • 需要支持 IE9 及以下浏览器
    • 无法修改服务器配置
    • 项目较简单,对 URL 格式要求不高
  2. 使用 History 模式当

    • 只需支持现代浏览器
    • 可以配置服务器
    • 需要更优雅的 URL 格式

6.2 注意事项

  1. Hash 模式注意点

    • hash 值不会发送到服务器
    • SEO 不友好
    • URL 不够美观
  2. History 模式注意点

    • 需要服务器配置支持
    • 刷新页面可能 404
    • 需要处理前进/后退事件

6.3 性能优化

  1. 路由懒加载
const router = new VueRouter({routes: [{path: '/about',component: () => import('./components/About.vue')}]
});
  1. 预加载
// 在空闲时预加载其他路由组件
const PreloadAbout = () => {const link = document.createElement('link');link.rel = 'prefetch';link.href = '/about.chunk.js';document.head.appendChild(link);
};

7. 总结

  1. 技术选择

    • 根据项目需求选择合适的路由模式
    • 考虑浏览器兼容性要求
    • 评估服务器配置能力
  2. 开发建议

    • 合理使用路由懒加载
    • 做好错误处理
    • 注意 URL 规范性
  3. 维护考虑

    • 保持路由结构清晰
    • 做好文档记录
    • 考虑后续扩展性
      在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/501223.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

头歌实训数据结构与算法 - 字符串匹配(第2关:实现KMP字符串匹配)

任务描述 本关任务&#xff1a;编写一个程序&#xff0c;利用kmp算法求子串在主串中不重叠出现的次数。 实验目的&#xff1a;深入掌握KMP算法的应用。实验内容&#xff1a;编写一个程序&#xff0c;利用KMP算法求子串t在主串s中出现的次数&#xff0c;例如&#xff1a;s“aa…

enzymejest TDD与BDD开发实战

一、前端自动化测试需要测什么 1. 函数的执行逻辑&#xff0c;对于给定的输入&#xff0c;输出是否符合预期。 2. 用户行为的响应逻辑。 - 对于单元测试而言&#xff0c;测试粒度较细&#xff0c;需要测试内部状态的变更与相应函数是否成功被调用。 - 对于集成测试而言&a…

UE5通过蓝图节点控制材质参数

通过蓝图节点控制材质的参数 蓝图节点 在材质上设置标量值 和 在材质上设置向量参数值 Set Scalar Parameter Value on Materials Set Vector Parameter Value on Materials 这两个蓝图节点都可以在蓝图中&#xff0c;控制材质的参数值和向量值

MySQL秘籍之索引与查询优化实战指南

MySQL秘籍之索引与查询优化实战指南 目录 MySQL秘籍之索引与查询优化实战指南相关阅读索引相关EXPLAIN 版本 1. 初级篇1.1 【练体术】基础1.1.1 库操作1.1.1 表操作创建一个表增加表字段 1.1.2 增删改插入一条数据删除一条数据更新一条数据库 1.1.3 查询查询所有数据条件查询&a…

沁恒CH32V208GBU6蓝牙MTU二:减小连接间隔提升速度;修改GAP里面的连接参数提高兼容性

从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…

探索 Vue.js 的动态样式与交互:一个有趣的样式调整应用

修改日期备注2025.1.3初版 一、前言 今天和大家分享在 Vue.js 学习过程中开发的超酷的小应用。这个应用可以让我们通过一些简单的交互元素&#xff0c;如复选框、下拉菜单和输入框&#xff0c;来动态地改变页面上元素的样式哦 让我们一起深入了解一下这个项目的实现过程&…

Python应用指南:高德交通态势数据

在现代城市的脉络中&#xff0c;交通流量如同流动的血液&#xff0c;交通流量的动态变化对出行规划和城市管理提出了更高的要求。为了应对这一挑战&#xff0c;高德地图推出了交通态势查询API&#xff0c;旨在为开发者提供一个强大的工具&#xff0c;用于实时获取指定区域或道路…

整合版canal ha搭建--基于1.1.4版本

开启MySql Binlog&#xff08;1&#xff09;修改MySql配置文件&#xff08;2&#xff09;重启MySql服务,查看配置是否生效&#xff08;3&#xff09;配置起效果后&#xff0c;创建canal用户&#xff0c;并赋予权限安装canal-admin&#xff08;1&#xff09;解压 canal.admin-1…

物联网控制期末复习

第3章 物联网控制系统的过程通道设计 3.1 模拟量输出通道 3.1.1单模拟量输出通道的构成 计算机控制系统的模拟量输出通道将计算机产生的数字控制信号转换为模拟信号&#xff08;电压或电流&#xff09;作用于执行机构&#xff0c;以实现对被控对象的控制。 多D/A结构&#…

python生成、操作svg图片

生成svg图片 通过python生成svg图片的方法有许多&#xff0c;比如OpenCV的源码中有svgfig.py这个脚本可以用于生成svg图片(OpenCV的棋盘格图片可以通过这个方法生成)&#xff0c;也可以使用svg.py的库&#xff0c;安装方法如下 pip install svg.py 下面是通过这个库生成一个简…

2024年大型语言模型(LLMs)的发展回顾

2024年对大型语言模型&#xff08;LLMs&#xff09;来说是充满变革的一年。以下是对过去一年中LLMs领域的关键进展和主题的总结。 GPT-4的壁垒被打破 去年&#xff0c;我们还在讨论如何构建超越GPT-4的模型。如今&#xff0c;已有18个组织拥有在Chatbot Arena排行榜上超越原…

Servlet解析

概念 Servlet是运行在服务端的小程序&#xff08;Server Applet)&#xff0c;可以处理客户端的请求并返回响应&#xff0c;主要用于构建动态的Web应用&#xff0c;是SpringMVC的基础。 生命周期 加载和初始化 默认在客户端第一次请求加载到容器中&#xff0c;通过反射实例化…

图片验证码如何显示在 Apifox 的响应控制台中

当接口返回的响应数据结构非常复杂&#xff0c;充斥着嵌套的对象和数组&#xff0c;其中还可能包含着图片的 URL 时&#xff0c;如果要查找特定信息&#xff0c;你需要不断上下滚动 JSON 响应&#xff0c;试图找到所需的字段。这不仅让人恼火&#xff0c;还浪费了宝贵的时间。 …

设计模式 创建型 单例模式(Singleton Pattern)与 常见技术框架应用 解析

单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在确保某个类在应用程序的生命周期内只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这种设计模式在需要控制资源访问、避免频繁创建和销毁对象的场景中尤为有用。 一、核心…

《Xsens动捕与人形机器人训练》讲座将于1月9日下午2:30在线上召开

《Xsens动捕与人形机器人训练》讲座将于1月9日下午2:30在线上召开&#xff0c;本次讲座中来自Xsens的人形机器人与动捕技术专家Jeffrey Muller与Dennis Kloppenburg不仅将就Xsens动作捕捉系统与人形机器人行为训练中的实际应用进行详细讲解&#xff0c;同时还会对目前大家所关注…

Flutter踩坑记-第三方SDK不兼容Gradle 8.0,需适配namespace

最近需要集成Flutter作为Module&#xff0c;Flutter依赖了第三方库&#xff0c;Gradle是8.0版本。 编译报错&#xff1a; 解决办法是在.android根目录下的build.gradle下新增一行代码&#xff1a; buildscript {ext.kotlin_version "1.8.22"repositories {google()…

Linux驱动开发学习准备(Linux内核源码添加到工程-Workspace)

Linux内核源码添加到VsCode工程 下载Linux-4.9.88源码&#xff1a; 没有处理同名文件的压缩包&#xff1a; https://pan.baidu.com/s/1yjIBXmxG9pwP0aOhW8VAVQ?pwde9cv 已把同名文件中以大写命名的文件加上_2后缀的压缩包&#xff1a; https://pan.baidu.com/s/1RIRRUllYFn2…

ImageNet 2.0?自动驾驶数据集迎来自动标注新时代

引言&#xff1a; 3DGS因其渲染速度快和高质量的新视角合成而备受关注。一些研究人员尝试将3DGS应用于驾驶场景的重建。然而&#xff0c;这些方法通常依赖于多种数据类型&#xff0c;如深度图、3D框和移动物体的轨迹。此外&#xff0c;合成图像缺乏标注也限制了其在下游任务中的…

朱姆沃尔特隐身战舰:从失败到威慑

前言 "朱姆沃尔特"号驱逐舰是美国海军雄心勃勃的项目&#xff0c;旨在重塑未来海战。它融合了隐身、自动化和强大火力&#xff0c;然而由于技术问题和预算超支&#xff0c;原计划建造32艘的目标被大幅缩减&#xff0c;最终只建造了三艘。该舰的设计特点包括“穿浪逆船…

电子电器框架 --- 电动汽车上的车载充电器(OBC)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…