详解JavaScript实现监听路由变化

yizhihongxing

那么就让我来详细讲解一下“详解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日

相关文章

  • JS中的进程和线程详解

    JS中的进程和线程详解 前言 JavaScript是一种单线程脚本语言,这就决定了它只能同时做一件事情。但是在一些新的开发需求和场景下,我们需要在JavaScript中模拟多线程。 进程和线程 在JS中,进程是指浏览器进程,线程就是指浏览器内部的线程。每一个页面都可以看做是一个独立的进程,同时在页面中可以创建多个线程来提高性能。 Web Worker Web…

    JavaScript 2023年5月27日
    00
  • 基于RequireJS和JQuery的模块化编程——常见问题全面解析

    标题:基于RequireJS和JQuery的模块化编程——常见问题全面解析 什么是模块化编程 模块化编程是指将一个复杂的程序拆分成多个模块,每个模块都具有独立的功能和接口,不同的模块可以灵活地组合在一起,构成复杂的应用程序。模块能够有效地提高代码的可重用性和可维护性,方便团队合作开发。 为何要使用RequireJS和JQuery RequireJS是一个AM…

    JavaScript 2023年5月27日
    00
  • js中通过getElementsByName访问name集合对象的方法

    获取name集合对象是DOM中的常见操作之一,使用getElementsByName方法可以获取到相应名字的元素节点集合。下面为大家提供选定属性值的两条示例说明: 语法说明 getElementsByName方法通过指定元素的name特定属性来获取文档中具有相同name属性值的元素集合。其基本语法如下: var elements = document.get…

    JavaScript 2023年6月10日
    00
  • js实现时间轴自动排列效果

    下面我将详细讲解如何使用JavaScript实现时间轴自动排列效果。 概述 时间轴是一种将时间点或事件与轴上的点或线连接起来的可视化工具,被广泛应用于各个网站的设计中。自动排列效果指的是时间轴上的点或线可以自动按照时间顺序排列显示。下面我们将分步骤详细介绍如何使用JavaScript实现这个效果。 步骤 1. 准备数据 首先需要准备一个包含时间信息的数据,通…

    JavaScript 2023年5月27日
    00
  • js动态设置div的值下例子

    下面让我来详细讲解“js动态设置div的值”的完整攻略。 基本概念 在开始具体的实现代码之前,我们先来了解一下这个问题的基本概念。 动态设置div的值:指的是通过JavaScript脚本代码实现在网页中的某个元素(如div)中动态设置内容,而不是直接在HTML代码中写死。 实现过程 实现动态设置div的值可以分为以下两个步骤: 1. 获取div元素 在Jav…

    JavaScript 2023年6月11日
    00
  • javascript asp教程错误处理

    接下来我将会给出一个完整的JavaScript ASP教程错误处理攻略,包含代码示例。 JavaScript ASP教程错误处理攻略 什么是错误处理? 在ASP中,错误处理是用于捕获和解决在代码运行时发生的错误和异常的技术。当您的代码出现错误时,错误处理将停止代码的执行, 并提供一些信息,比如错误类型、行号、错误描述等等,以方便调试和修复页面。 如何进行错误…

    JavaScript 2023年6月10日
    00
  • JS高级笔记

    关于“JS高级笔记”的完整攻略,以下是一些需要注意的重点: 1. 确定学习JS高级笔记的前置知识 在学习JS高级笔记之前,需要掌握JavaScript的基础语法、DOM操作、事件处理、AJAX等相关基础知识。只有理解这些基础知识,才能更好地理解JS高级笔记中的概念和实现方式。 2. 学习JavaScript的面向对象编程 JS高级笔记的很多内容都是基于Jav…

    JavaScript 2023年5月18日
    00
  • 详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结

    让我来为你详细讲解“详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结”。 1. 确认数据更新 首先,如果你发现Vue数据更新了但页面没有更新,应该先确保数据确实发生了改变。可以使用一些 Vue.js 开发者工具(比如 vue-devtools)来检查组件的数据是否确实发生了变化。 2. 检查 Vue 模板语法 在 Vue 模板语法中,有些写法…

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