详解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中BOM,DOM和事件的用法详解

    JavaScript中BOM,DOM和事件的用法详解 BOM是什么? BOM是指浏览器对象模型(Browser Object Model),它提供了对浏览器窗口的访问和控制。 窗口对象(Window Object) 窗口对象是BOM的顶层对象,它表示整个浏览器窗口或框架。窗口对象是可由脚本访问和操作的对象,通过它,可以控制当前窗口或框架的各项属性。 示例:获…

    JavaScript 2023年6月10日
    00
  • jquery使用$(element).is()来判断获取的tagName

    使用$(element).is()方法可以判断某个元素的标签名是否为指定标签名或其它选择器。 语法 $(element).is(selector) 参数 selector:一个字符串,表示标签名或其他选择器。 返回值 true:如果指定元素匹配选择器,返回true。 false:如果指定元素不匹配选择器,返回false。 示例 示例1:判断元素的标签名 判断…

    JavaScript 2023年6月10日
    00
  • js正则表达式校验指定字符串的方法

    当我们需要限制用户输入的内容,校验用户输入的内容是否符合规范时,就需要用到正则表达式。本文将详细讲解如何使用JavaScript正则表达式校验指定字符串的方法。 一、正则表达式的基本语法 在使用正则表达式前,需要了解其基本语法。正则表达式是由字符和操作符组合而成的字符串,用于描述匹配一系列符合某个句法规则的字符串。下面是几个常用的正则表达式操作符: /^ 符…

    JavaScript 2023年5月28日
    00
  • 统一接口:为FireFox添加IE的方法和属性的js代码

    为Firefox浏览器添加IE的方法和属性的js代码,需要使用jQuery以及XMLHttpRequest对象来实现。 以下是添加IE方法的代码: // 为IE的String对象添加contains方法 if (!String.prototype.contains) { String.prototype.contains = function(str, st…

    JavaScript 2023年6月10日
    00
  • JS对象数组中如何匹配某个属性值

    针对这个问题,我们可以分为以下几个步骤进行说明: 定义一个JS对象数组; 遍历数组,检查所有对象是否包含指定的属性值; 如果找到指定的对象,就返回该对象;如果没有找到,就返回 undefined。 下面是具体的代码实现和示例: 定义 JS 对象数组 首先我们需要定义一个包含一组 JS 对象的数组,如下所示: let students = [ { id: 1,…

    JavaScript 2023年6月10日
    00
  • JavaScript中变量提升 Hoisting

    JavaScript中变量提升 Hoisting 在JavaScript中,变量提升指的是在代码执行之前,JavaScript引擎将所有的变量声明提升到作用域的顶部,无论这些变量是在何处声明的。这意味着我们可以在变量声明之前使用变量。 变量提升的过程 当JavaScript代码在执行之前被解析时,所有的变量声明都被提升到了函数或全局作用域的顶部。这个过程被称…

    JavaScript 2023年6月10日
    00
  • json字符串传到前台input的方法

    将JSON字符串传到前台input可以通过JavaScript的方式实现。主要分为两个步骤: 将JSON字符串赋值给JavaScript变量或对象 将变量或对象中的值赋值给input 下面分别详细说明这两个步骤。 将JSON字符串赋值给JavaScript变量或对象 首先,我们需要将JSON字符串转换为JavaScript对象。这可以通过JSON.parse…

    JavaScript 2023年5月27日
    00
  • JavaScript初级教程(第三课)

    下面是“JavaScript初级教程(第三课)”的完整攻略: JavaScript初级教程(第三课) 概述 本课程将介绍 JavaScript 中的数据类型和变量。在编程中,变量被用来存储数据,而不同的数据类型可以存储不同类型的数据。因此,了解 JavaScript 中的数据类型和变量是非常重要的。 数据类型 JavaScript 中有以下几种常见的数据类型…

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