当前位置: 首页 > 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/a/295066.html

相关文章:

  • 力扣104 : 二叉树最大深度
  • 24.11.13 Javascript3
  • 基于迭代重加权最小二乘法的算法及例程
  • wafw00f源码详细解析
  • Xcode 16 使用 pod 命令报错解决方案
  • centos7上安装mysql
  • 反弹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语言实现,超详细!!!)