当前位置: 首页 > article >正文

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

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 改变 URL
    window.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.kler.cn/news/295066.html

相关文章:

  • 反弹shell
  • 【Python报错已解决】 AttributeError: ‘move_to‘ requires a WebElement
  • Redis单机安装
  • 国开(电大)2024秋《文献检索与论文写作》综合练习2
  • 云服务器部署DB-GPT项目
  • 自动驾驶---Motion Planning之轨迹拼接
  • WIN11 ESP32 IDF + VSCODE 环境搭建[教程向]
  • 不会Excel怎么制作桑基图?用什么软件绘制比较好呢?推荐2款简单好用的图表制作工具
  • c++递推
  • 拉取ros2_control_demos存储库
  • List中常见的方法和五种遍历方式
  • windows下使用vscode编写运行以及调试C/C++
  • 基于STM32设计的ECG+PPG人体参数测量系统(华为云IOT)(217)
  • ROS1 + Realsense d455 固件安装+读取rostopic数据
  • nmon服务器监控工具使用
  • 请解释Java Web应用中的前后端分离是什么?它有哪些好处?什么是Java Web中的Servlet过滤器?它有什么作用?
  • ffmpeg的安装和使用教程
  • python--基础语法(1)
  • 《Ajax 是什么?如何在 HTML5 中使用》
  • 数据结构--二叉树(C语言实现,超详细!!!)
  • 彩色成像的基础和应用 原理 Principles (论文引用目录)
  • 2024年高教社杯数学建模国赛C题超详细解题思路分析
  • 图论篇--代码随想录算法训练营第五十天打卡| 深度优先搜索理论基础,98. 所有可达路径,广度优先搜索理论基础
  • 数字化转型专家讲师培训师唐兴通中欧国际工商学院数字化转型战略与实现路径AIGC人工智能数字化战略数字商业模式创新
  • 【数据库中级】1_DBeaver操作数据库
  • 【微信小程序】搭建项目步骤 + 引入Tdesign UI
  • Flink SQL 中常见的数据类型
  • 开源网安引领AIGC+开发安全,智能防护铸就软件安全新高度
  • 【Springboot基础知识】
  • 基于 rt-thread的I2C操作EEPROM(AT24C02)