详解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日

相关文章

  • 表单元素事件 (Form Element Events)

    当用户在表单中进行提交、清空、选择、输入等操作时,表单元素可以触发不同类型的事件。开发者可以通过JavaScript处理这些事件,以实现表单的交互功能和数据处理。 以下是几种常见的表单元素事件及其用法: 1. onSubmit事件: 当表单被提交时,会触发onSubmit事件。通常用于表单的校验和提交处理。 <form onsubmit="r…

    JavaScript 2023年6月10日
    00
  • flash调用js中的方法,让js传递变量给flash的办法及思路

    实现Flash调用JS方法并接收JS传递的变量有以下两种常见做法: 一、使用 ExternalInterface 作为一个Flash插件的开发者,可以使用 ExternalInterface 达到让 Flash 调用 JavaScript,让 JavaScript 调用 Flash 之间互相交互的目的。 以下是一个示例说明: Flash定义和带入数据 Fla…

    JavaScript 2023年6月11日
    00
  • 一个简单的js动画效果代码

    下面我来详细讲解如何编写一个简单的js动画效果代码。 准备工作 在编写动画代码前,需要准备好HTML文件和CSS文件。 HTML文件 假设需要给一个按钮添加动画效果,我们可以在HTML文件中添加一个按钮元素,如: <button id="btn">按钮</button> CSS文件 我们要将按钮的样式设为相对定位(…

    JavaScript 2023年6月10日
    00
  • 把js文件编译成dll供页面调用的方法

    下面我会详细讲解如何把js文件编译成dll供页面调用的方法。步骤如下: 1. 安装webpack和webpack-dev-server 首先需要全局安装webpack和webpack-dev-server。运行以下命令: npm install webpack -g npm install webpack-dev-server -g 2. 创建webpack…

    JavaScript 2023年5月27日
    00
  • Json Web Token在前后端实践思考分析

    Json Web Token在前后端实践思考分析 什么是Json Web Token(JWT) JSON Web Token(JWT)是一种用于在两个实体之间安全传输消息的开放标准(RFC 7519)。JWT以JSON格式编码数据,可以安全地存储在URL参数、POST参数、HTTP标头或Cookie中。JWT包括三个部分:头部,载荷和签名,最终生成的JWT字…

    JavaScript 2023年5月27日
    00
  • JavaScript代码实现简单日历效果

    JavaScript代码实现简单日历效果 引言 日历是人们生活中必不可少的一部分,Javascript通过操作DOM元素以及CSS样式,实现了多种简单的日历效果。本文将详细介绍JavaScript如何实现一个简单的日历效果。 分析与目标 首先,我们要对一个日历的样式进行分析,发现日历主要是由星期和日期构成的,其次各个日期的显示状态需通过计算天数来完成。 所以…

    JavaScript 2023年5月27日
    00
  • 前端编码规范(3)JavaScript 开发规范

    前端编码规范对于一个团队而言是非常重要的,它有助于提高代码的可阅读性、可维护性,并能够帮助团队成员之间保持协同配合。本文主要讲解 JavaScript 开发规范,下面将详细介绍该规范的内容。 1. 变量与常量命名规范 在 JavaScript 开发中,变量与常量命名应当遵循以下规范: 变量和常量名应该基于语义而非单词缩写 全局变量使用 全大写常量 的方式定义…

    JavaScript 2023年5月18日
    00
  • javascript字母大小写转换的4个函数详解

    下面是“Javascript字母大小写转换的4个函数详解”的完整攻略。 1. toUpperCase()函数 该函数可以将字符串中的字母全部转换成大写。 语法格式: string.toUpperCase(); 示例: var str1 = ‘hello world’; console.log(str1.toUpperCase()); // 输出: ‘HELL…

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