手写 Vue Router 中的 Hash 模式和 History 模式

server/2024/10/19 14:54:14/

Vue Router Vue.js 的官方路由库,负责管理 Vue应用中的页面导航。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。Vue Router 提供两种常见的模式:Hash 模式History 模式。这两种模式的主要区别在于它们如何管理 URL,以及如何与浏览器的历史记录 API 交互。

1. URL 路由的基本概念

Vue RouterVue 官方的客户端路由解决方案。

客户端路由的作用是在单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载。

Vue Router 基于 Vue 的组件系统构建,你可以通过配置路由来告诉 Vue Router 为每个 URL 路径显示哪些组件。路由的主要任务包括:

  • 根据 URL 切换不同的页面组件。
  • 动态管理浏览器的历史记录和导航状态。

Vue Router 使用两种方式来实现路由:

  • Hash 模式:利用 URL 中的 # 符号(例如 http://example.com/#/home),基于 hashchange事件进行路由切换。
  • History 模式:利用 HTML5 的 History API(pushStatereplaceState)实现路径导航(例如 http://example.com/home),更贴近传统多页面应用的 URL 形式。

2. 实现 Hash 模式的 Vue Router

Hash 模式是最简单的一种实现方式,它依赖于浏览器原生的 hashchange 事件。下面我们通过手写代码实现一个简化版的 Hash 模式。

2.1 Hash 模式核心代码

class Router {constructor(routes) {this.routes = routes;  // 路由规则this.currentPath = ''; // 当前路径this.init();}// 初始化监听init() {// 页面加载时触发路由匹配window.addEventListener('load', this.onHashChange.bind(this));// 当 hash 改变时,触发路由匹配window.addEventListener('hashchange', this.onHashChange.bind(this));}// 获取当前 hash 路径并匹配路由onHashChange() {// 去掉 # 并获取当前的路径this.currentPath = window.location.hash.slice(1) || '/';this.matchRoute();}// 匹配路径对应的组件并渲染matchRoute() {const route = this.routes.find(r => r.path === this.currentPath);if (route) {document.getElementById('app').innerHTML = route.component;} else {document.getElementById('app').innerHTML = '404 Not Found';}}
}

2.2 示例代码
我们可以定义一些简单的路由和组件,并启动这个简化版的 Hash 模式路由。


<div id="app"></div><script>// 定义路由规则const routes = [{ path: '/', component: '<h1>Home Page</h1>' },{ path: '/about', component: '<h1>About Page</h1>' },{ path: '/contact', component: '<h1>Contact Page</h1>' },];// 创建路由实例const router = new Router(routes);
</script>

当用户访问 /#/about 时,hashchange 事件会触发,路由器会匹配 /about 路径,并在页面上渲染 About Page 组件。

2.3 Hash 模式的优缺点

优点:

  • 简单易实现,几乎所有浏览器都支持 hashchange 事件。
  • 不需要服务器配置即可使用,因为 hash 不会被发送到服务器。

缺点:

  • URL 中包含 # 符号,显得不够美观。
  • SEO 不友好,搜索引擎不会解析 # 后面的内容。

3. 实现 History 模式的 Vue Router

vue-router 默认 hash 模式 —— 使用 URLhash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。该模式基于 HTML5 的 pushStatereplaceState API,能够改变浏览器的 URL 而不刷新页面。这种方式让 URL 更加简洁,不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

3.1 History 模式核心代码

class Router {constructor(routes) {this.routes = routes;  // 路由规则this.currentPath = window.location.pathname; // 当前路径this.init();}// 初始化监听init() {// 页面加载时触发路由匹配window.addEventListener('load', this.onPathChange.bind(this));// 浏览器前进后退时触发路由匹配window.addEventListener('popstate', this.onPathChange.bind(this));// 绑定导航点击事件document.querySelectorAll('a[data-link]').forEach(link => {link.addEventListener('click', this.onLinkClick.bind(this));});}// 处理路径变化onPathChange() {this.currentPath = window.location.pathname;this.matchRoute();}// 匹配路径并渲染组件matchRoute() {const route = this.routes.find(r => r.path === this.currentPath);if (route) {document.getElementById('app').innerHTML = route.component;} else {document.getElementById('app').innerHTML = '404 Not Found';}}// 拦截导航链接点击事件onLinkClick(event) {event.preventDefault();const path = event.target.getAttribute('href');// 使用 pushState 改变 URLwindow.history.pushState({}, '', path);this.onPathChange();}
}

3.2 示例代码
为配合 pushState 的使用,我们需要在页面上创建一些导航链接,并通过点击这些链接进行页面切换。

<div id="app"></div>
<nav><a href="/" data-link>Home</a><a href="/about" data-link>About</a><a href="/contact" data-link>Contact</a>
</nav><script>// 定义路由规则const routes = [{ path: '/', component: '<h1>Home Page</h1>' },{ path: '/about', component: '<h1>About Page</h1>' },{ path: '/contact', component: '<h1>Contact Page</h1>' },];// 创建路由实例const router = new Router(routes);
</script>

在这个示例中,当点击导航链接时,pushState 改变 URL,但不会触发页面刷新,而是通过 Router 手动渲染对应的组件。

3.3 History 模式的优缺点

优点:

  • URL 更加美观,没有 # 符号。
  • 更加符合传统的多页面应用,用户体验更好。
  • SEO 更友好,搜索引擎可以解析 URL

缺点:
-需要服务器配合,所有请求必须返回 index.html,否则会出现 404 错误。

4. 总结

通过手写简化版的 Vue Router,我们深入理解了 Hash 模式History 模式 的实现原理。Hash 模式依赖于 hashchange 事件,而 History 模式依赖于 pushStatereplaceState API。两种模式各有优缺点,可以根据项目需求选择合适的路由模式。

  • Hash 模式:简单、无需服务器配置,但 URL 不美观,对 SEO 不友好。
  • History 模式:URL 美观且符合 SEO 要求,但需要服务器支持。

无论是简单的项目还是大型的单页面应用,Vue Router 都提供了强大的路由管理能力,通过深入了解其原理,我们可以更灵活地运用它来构建现代 Web 应用。


http://www.ppmy.cn/server/113543.html

相关文章

go的父子类的简单使用

简介 go的父子类&#xff0c;感觉类似于基类和基于基类的扩展类&#xff0c;然后子类基于父类做一些用法的扩充&#xff0c;有些类似于抽象类和其子类的实现 代码如下 package parentchildclassimport "fmt"type WriteInterface interface {Write() }type WritePa…

1-19 平滑处理——双边滤波 opencv树莓派4B 入门系列笔记

目录 一、提前准备 二、代码详解 cv2.bilateralFilter函数用于对图像进行双边滤波。双边滤波是一种保持边缘的平滑技术&#xff0c;常用于图像去噪声和增强图像的细节。函数的四个参数如下&#xff1a; 三、运行现象 四、完整工程贴出 一、提前准备 1、树莓派4B 及 64位系统…

【iOS】折叠cell

折叠cell 前言实现原理代码实现原理讲解代码展示 前言 暑假在仿写3G share时使用到了折叠cell&#xff0c;故而现在来总结一下折叠cell&#xff0c;如有不足&#xff0c;还望指正。 实现原理 在OC中&#xff0c;scrollview是tableview的父类&#xff0c;要想实现折叠cell的效…

Redis的设计哲学和实现方式

‌ Redis是一个可用性和分区容忍性优先的系统。 Redis的设计和实现强调了高可用性和高性能&#xff0c;而不是严格的数据一致性。 这一点可以从Redis的分布式设计、数据压缩支持、以及异步IO机制等方面看出。 ‌分布式设计与数据一致性‌&#xff1a;Redis的分布式设计中采用了…

rust feature 简介

Rust 的 feature 是一种机制&#xff0c;用于在编译时选择性地启用或禁用代码的某些部分。通过 feature&#xff0c;你可以在 Cargo.toml 中定义哪些功能需要启用&#xff0c;并在代码中通过条件编译来控制代码的编译与否。下面是 feature 机制的详解&#xff1a; 1. 基本概念…

一文梳理RAG(检索增强生成)的现状与挑战

一 RAG简介 大模型相较于过去的语言模型具备更加强大的能力&#xff0c;但在实际应用中&#xff0c;例如在准确性、知识更新速度和答案透明度方面&#xff0c;仍存在不少问题&#xff0c;比如典型的幻觉现象。因此&#xff0c;检索增强生成 (Retrieval-Augmented Generation, …

Maven快速上手使用指南的笔记

Maven Mini Guides Configuring for Reproducible Builds 使用Maven实现重复构建。 检查当前使用的插件的版本。 mvn artifact:check-buildplan修改pom.xml&#xff0c;增加如下配置&#xff0c;显式指定project.build.outputTimestamp的取值&#xff1a; <properties>…

ubantu安装mysql + redis数据库并使用C/C++操作数据库

mysql 安装mysql ubuntu 安装 MySql_ubuntu安装mysql-CSDN博客 Ubuntu 安装 MySQL 密码设置_ubuntu安装mysql后设置密码-CSDN博客 service mysql restart1 C/C连接数据库 C/C 连接访问 MySQL数据库_c mysql-CSDN博客 ubuntu安装mysql的c开发环境_ubuntu 搭建mysql c开发…