前端开发中的路由模式

前言

前端开发中的路由是一个关键概念,它负责确定页面内容的显示和URL的管理。无论你是用vue-router还是react-router,通常有两种常见的模式,即路由哈希(Hash)模式和历史(History)模式,无论那种模式都可在URL变化的同时,不触发HTML物理文件的重新加载。在本文中,我将详细介绍这两种路由模式的实现原理和区别,以及提供相应的代码示例。

路由的概念

路由是一种将URLWeb应用程序中的不同视图或页面关联起来的机制。它允许用户通过浏览器的地址栏或导航操作来切换和访问不同的页面或视图,而无需重新加载整个页面。路由在单页面应用程序(SPA)中特别有用,因为SPA通常仅加载一次,而后续页面切换通过路由来实现。

路由哈希(Hash)模式

实现原理

路由哈希模式使用URL中的哈希(#)来管理路由。在这种模式下,会在原有的URL路径后面拼接/#/xxx,这种方式可以在不重新加载原有HTML文件的基础上,实现切换URL路径的目的。实现路由哈希模式的关键是监听window.location.hash属性的变化。

  1. 当用户点击链接或进行导航时,JavaScript代码会监听到哈希变化事件。

  2. JavaScript代码解析新的哈希值,根据哈希值来渲染相应的页面内容。

  3. 页面内容的变化通过JavaScript来实现,而此时浏览器地址栏的URL变为主URL之后带有哈希值的状态。

代码示例

以下是一个使用路由哈希模式的简单代码示例:

<!DOCTYPE html>
<html>
<head>
  <title>Hash Routing Example</title>
</head>
<body>
  <ul>
    <li><a href="#/home">Home</a></li>
    <li><a href="#/about">About</a></li>
    <li><a href="#/contact">Contact</a></li>
  </ul>
  <div id="content"></div>

  <script>
    // 监听哈希变化事件
    window.addEventListener("hashchange", function() {
      // 获取当前哈希值
      const hash = window.location.hash;

      // 渲染相应的页面内容
      const content = document.getElementById("content");
      if (hash === "#/home") {
        content.innerHTML = "Welcome to the Home page!";
      } else if (hash === "#/about") {
        content.innerHTML = "This is the About page.";
      } else if (hash === "#/contact") {
        content.innerHTML = "Contact us here.";
      } else {
        content.innerHTML = "Page not found.";
      }
    });
  </script>
</body>
</html>

在上述示例中,我们通过监听hashchange事件来实现路由哈希模式。当用户点击链接时,URL中的hash部分发生变化,会触发函数通知,通过JavaScirpt编程可以很快速的实现Dom对象的切换展示。哈希模式也有不足之处,如在分布式微前端项目中,嵌套的子应用和主应用都使用哈希模式时,由于哈希模式的URL路径只能存在一个#,会导致子应用和主应用在定义URL路径上存在困难。当然哈希模式的URL路径中包含#,也会在视觉上存在URL不美观的问题。

历史(History)模式

实现原理

历史模式使用history对象中的pushState()replaceState()函数重写URL路径。这种模式允许开发人员更自由地操作浏览器的历史记录,而无需使用哈希。

  1. 开发人员使用history.pushStatehistory.replaceState添加或修改浏览器历史记录中的条目,同时更新URL。

  2. 页面内容的变化通过JavaScript来实现,而浏览器地址栏的URL也会更加友好,不再包含哈希。

代码示例

以下是一个使用历史模式的简单代码示例:

<!DOCTYPE html>
<html>

<head>
    <title>History Routing Example</title>
</head>

<body>
    <ul>
        <li><a href="javascript:jump('/about')">About</a></li>
        <li><a href="javascript:jump('/contact')">Contact</a></li>
    </ul>
    <div class="page about" style="display: none">
        This is the About page.
    </div>
    <div class="page contact" style="display: none">
        This is the Contact page.
    </div>
    <script type="text/javascript">
        function jump(path) {
            history.pushState({}, null, path);
            let pages = document.querySelectorAll(".page");
            let newPage = document.querySelector(path.replace("/", "."));
            pages.forEach((page) => {
                page.style.display = "none";
            });
            newPage.style.display = "block";
        }
    </script>
</body>

</html>

在上述示例中,我们使用history.pushState方法来实现路由历史模式。当用户点击链接时,页面的内容将根据URL的变化而更新。虽然history模式可以重写URL路径,但是重写后的新路径中并不包含原有HTML物理文件的访问地址,所以history模式在重写URL路径后,一旦刷新网页会造成404无法访问的效果。VueCLI在开发环境中解决了history模式的刷新问题,不过项目发布到生产环境时,由于history模式的URL路径问题,还需要配合生产服务器的转发规则重写,用以支持history模式的路由加载。

路由哈希模式与历史模式的区别

  1. URL形式:

- 路由哈希模式使用带有哈希的URL,如http://example.com/#/home

- 历史模式使用常规的URL路径,如http://example.com/home

  1. 浏览器兼容性:

- 路由哈希模式在更旧的浏览器中通常具有更好的兼容性,因为它不需要HTML5的pushStatereplaceState

- 历史模式需要HTML5支持,较旧的浏览器可能不支持。

  1. 用户体验:

- 历史模式提供更友好的URL,但可能需要更多的服务器配置,以便在刷新页面时正确处理URL。

- 路由哈希模式在刷新页面时不会向服务器发送请求,因为哈希不会被包含在HTTP请求中。

  • 服务器配置:

    • 路由哈希模式不需要特殊的服务器配置,因为哈希部分不会被发送到服务器。
    • 历史模式需要服务器配置,以确保在刷新页面时正确处理URL,并将所有请求指向同一入口点。
  • SEO(搜索引擎优化):

    • 路由哈希模式在SEO方面可能稍逊色,因为搜索引擎对于哈希部分的处理可能有所限制。
    • 历史模式对SEO更友好,因为搜索引擎可以更轻松地解析常规的URL路径。
  • 代码简洁性:

    • 路由哈希模式的实现通常比较简单,因为不涉及服务器配置,并且哈希变化事件比较容易监听。
    • 历史模式的实现可能需要更多的配置和处理,特别是在处理刷新页面时保持路由状态的情况下。

总结

路由哈希模式和历史模式都是前端路由的常见实现方式,各自有其优势和劣势。选择哪种模式取决于项目的需求、服务器环境和对SEO的关注程度。在实际项目中,可以根据具体情况选择适合的路由模式,或者在需要时结合使用。