详解JavaScript实现监听路由变化

那么就让我来详细讲解一下“详解JavaScript实现监听路由变化”的完整攻略吧。

一、引言

当我们使用现代化 JavaScript 框架时,我们通常需要动态地更新页面视图以匹配 URL 路径中的路由而不进行任何页面重新加载。这就是我们需要路由监听的原因,以更新浏览器 URL 的时候同时不需要全量渲染页面。在本文中,我们会一起探讨如何实现 JavaScript 的路由监听。

二、使用JavaScript实现监听路由变化

路由的监听是实现单页面应用 (SPA) 的主要轴心之一。在 JavaScript 应用程序中,我们通常使用路由来渲染不同的视图组件。以下是实现路由监听的基本步骤:

  1. 首先,我们需要为路由器设置监听器,并在路由变化时调用相应的函数。
  2. 我们需要使用 window.history.pushState API 来推动新路由并更新 URL。
  3. 我们需要使用 JavaScript 监听 popstate 事件在 URL 中更新路由时调用相应的函数。

这里还要说明的是在 HTML5 历史 API 中,我们通常使用 history.pushStatehistory.replaceState 这两个方法来添加和修改访问历史记录条目。这些方法可以使用浏览器历史 API 的 pushState, replaceState 和 popstate 方法来实现。

以下是一些示例代码,以便更好地理解 JavaScript 监听路由的过程。

示例1:

class Router {
  constructor(routes) {
    this.routes = routes;
    this._loadInitialRoute();
  }
  loadRoute(...url) {
    const matchedRoute = this._matchUrlToRoute(url);
    const urlSearchParams = this._splitUrlIntoParams(url);
    const queryParams = this._getParamsFromSearch(urlSearchParams);
    const routeParams = this._getParamsFromRoute(matchedRoute, url);
    matchedRoute.func({ ...routeParams, ...queryParams });
  }
  _getParamsFromRoute(route, url) {
    return route.path
      .split('/')
      .reduce((routeParams, routePathSegment, i) => {
        if (routePathSegment === '') {
          return routeParams;
        }
        if (routePathSegment[0] === ':') {
          return { ...routeParams, [routePathSegment.slice(1)]: url[i] };
        }
        return routeParams;
      }, {});
  }
  _getParamsFromSearch(search) {
    let queryParams = {};
    for (let [key, value] of search.entries()) {
      queryParams[key] = value;
    }
    return queryParams;
  }
  _splitUrlIntoParams(url) {
    const [, search] = url.toString().split('?');
    const urlSearchParams = new URLSearchParams(search);
    return urlSearchParams;
  }
  _matchUrlToRoute(urlSegments) {
    const matchedRoute = this.routes.find(route => {
      const routePathSegments = route.path.split('/').slice(1);
      if (routePathSegments.length !== urlSegments.length) {
        return false;
      }
      return routePathSegments.every(
        (routePathSegment, i) =>
          routePathSegment === urlSegments[i] || routePathSegment[0] === ':',
      );
    });
    return matchedRoute;
  }
  _loadInitialRoute() {
    const fullPathName = window.location.pathname;
    const urlSegments = fullPathName.split('/').slice(1);
    this.loadRoute(...urlSegments);
  }
}

const pageView = ({ title, content }) => {
  document.title = title;
  document.body.innerHTML = content;
};

const routes = [
  {
    path: '/',
    func: () =>
      pageView({ 
        title: 'HomePage', 
        content: '<h1>Welcome Home</h1>' 
     }),
  },
  {
    path: '/posts/:id',
    func: ({ id }) =>
      pageView({
        title: `Post ${id}`,
        content: `Displaying post ${id}`,
      }),
  },
  {
    path: '/query',
    func: ({ author, subject }) =>
      pageView({
        title: 'Query',
        content: `
            <ul>
              <li><strong>Author:</strong> ${author}</li>
              <li><strong>Subject:</strong> ${subject}</li>
            </ul>
          `,
      }),
  },
];

const router = new Router(routes);

document.querySelectorAll('a').forEach(link => {
  link.addEventListener('click', evt => {
    evt.preventDefault();
    const url = evt.target.getAttribute('href');
    const urlSegments = url.split('/').slice(1);
    router.loadRoute(...urlSegments);
    window.history.pushState({}, '', url);
 });
});

window.addEventListener('popstate', () => router.loadRoute(...location.pathname.split('/').slice(1)));

在上述示例代码中,我们创建了一个 Router 类的实例,该类有 loadRoute() 方法,该方法会通过传递给它的 URL 来查找匹配的路由并执行其函数。我们还设置了 window.history.pushState 必要的参数来推动新路由并更新 URL。我们用 popstate 事件监听器来在 URL 中更新路由时调用 loadRoute()

示例2:

function loadPage(view) {
  const script = document.createElement('script');
  script.src = view;
  document.getElementById('page-view').appendChild(script);
}

document
  .querySelectorAll('a')
  .forEach(link =>
    link.addEventListener('click', event => {
      event.preventDefault();
      loadPage(event.target.href);
      history.pushState({}, '', event.target.href);
    })
  );

window.addEventListener('popstate', () => {
  document.getElementById('page-view').innerHTML = '';
});

在此示例代码中,我们创建了一个 loadPage() 函数来加载选定视图的内容。在监听 click 事件的链接时,我们加载该链接的内容并在 URL 中推送新路由,使用户可以通过浏览器的前进和后退按钮导航。popstate 事件监听器一旦应用程序 URL 历史记录发生了变化,则会重新加载页面。

三、总结

在 JavaScript 应用程序中,使用路由监听是实现单页面 (SPA) 的主要方法之一。我们可以使用 window.history.pushState API 来推送新路由并更新 URL,使用 JavaScript 监听 popstate 事件以在 URL 中更新路由时调用相应的函数。

上面提供的示例代码可以帮助大家更好地了解JavaScript路由监听的原理和实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解JavaScript实现监听路由变化 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • JavaScript中的getDay()方法使用详解

    根据你的要求,我会用标准的markdown格式文本,为你详细讲解“JavaScript中的getDay()方法使用详解”的完整攻略。 JavaScript中的getDay()方法 在 JavaScript 中,Date 对象有一个 getDay() 方法,该方法用于获取一个星期的第几天,其返回值是一个 0 到 6 的整数,分别对应星期日到星期六。 语法如下:…

    JavaScript 2023年6月10日
    00
  • Web设计师如何制作Retina显屏设备的图片

    下面是Web设计师制作Retina屏幕设备图片的攻略: 1. 理解Retina屏幕设备的特点和需求 首先,我们需要理解Retina屏幕设备的特点和需求。 Retina屏幕设备比传统屏幕设备拥有更高的分辨率和像素密度,例如iPhone的Retina屏幕设备像素密度达到每英寸326个像素。这种高像素密度使得普通图片在Retina屏幕设备上显示效果模糊不清,因此需…

    JavaScript 2023年6月11日
    00
  • JS实现的文件拖拽上传功能示例

    JS实现的文件拖拽上传功能可以让用户通过拖拽文件到页面上的区域来上传文件,而不用手动选择文件上传。下面是实现文件拖拽上传功能的完整攻略: 步骤1:为文件拖拽区域添加事件监听器 需要为文件拖拽区域添加以下3个事件监听器: dragenter:当拖拽文件进入文件拖拽区域时触发,此时需要对文件拖拽区域的样式进行修改。 dragover:当鼠标在文件拖拽区域内移动时…

    JavaScript 2023年5月28日
    00
  • JavaScript JMap类定义与使用方法示例

    JavaScript JMap类定义与使用方法示例 JMap是JavaScript的一个扩展类,它提供了一种使用JSON格式存储数据的方式,可以轻松地实现数据的存储、读取、修改和删除等操作。 类定义 在使用JMap类之前,我们需要先定义一个JMap对象,可以使用以下代码: class JMap { constructor() { this.entries =…

    JavaScript 2023年5月28日
    00
  • MySQL pt-slave-restart工具的使用简介

    当MySQL复制出现异常时(如主从延迟、主从不同步),我们可以使用Percona Toolkit中的pt-slave-restart工具来帮助我们快速地解决问题。本篇攻略将详细讲解如何使用pt-slave-restart工具。 什么是pt-slave-restart工具 pt-slave-restart工具是Percona Toolkit中的一款工具,用于重…

    JavaScript 2023年5月28日
    00
  • JavaScript获取一个范围内日期的方法

    获取一个范围内日期的方法在JavaScript中有多种实现方式。我将一一介绍它们的实现方法和步骤。 方法一:利用Date对象的setDate()和getDate()方法 这种方法可以获取指定开始日期和结束日期之间的所有日期,只需要一个循环即可完成。 步骤 将开始日期和结束日期转换为Date对象。 const startDate = new Date(‘202…

    JavaScript 2023年5月27日
    00
  • Vue中router-link如何添加mouseover提示

    要在Vue中使用mouseover提示,我们可以使用title属性。而对于router-link组件,要使用mouseover提示,我们可以在组件内部使用slot来传递title属性。 以下是添加mouseover提示的步骤: 在router-link标签内部使用slot,传递属性title,如下所示: <router-link to="/&…

    JavaScript 2023年6月11日
    00
  • 你所不了解的javascript操作DOM的细节知识点(一)

    下面就为大家详细讲解“你所不了解的JavaScript操作DOM的细节知识点(一)”的完整攻略。 什么是DOM? DOM(文档对象模型)是指一种用于在HTML、XML等文档中描述元素的层次结构的API。通过DOM,JavaScript可以获取和修改文档的内容和结构。 元素节点和文本节点 在DOM中,每一个HTML元素都被表示为一个元素节点(element n…

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部