在本文中,我们将构建一个客户端路由系统。客户端路由是一种路由类型,用户在其中导航应用程序,即使页面的 URL 发生更改,也不会重新加载整个页面,而是显示新内容。

为了构建它,我们需要一个简单的服务器来提供我们的index.html文件。准备好?让我们开始。

让我们为我们的 HTML 创建一个简单的样板:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>Javascript Routing</h1><div id="app"></div><script src="main.js"></script>
</body>
</html>

在这里,我们将链接main.js文件,以便我们可以在任何时间点操作 DOM。

实现路由系统

让我们转到main.js文件并编写我们所有的路由器逻辑。我们所有的代码都将被包装在window.onload其中,以便它们仅在网页完全加载其所有内容后才执行脚本。

接下来,我们将创建一个路由器实例,它是一个带有两个参数的函数。第一个参数将是路线的名称,第二个参数将是一个包含我们定义的所有路线的数组。这条路线将有两个属性:路线的名称和路线的路径。

window.onload = () => {
// get root div for renderinglet root = document.getElementById('app');//router instancelet Router = function (name, routes) {return {name,routes}};//create the route instancelet routerInstance = new Router('routerInstance', [{path: "/",name: "Root"},{path: '/about',name: "About"},{path: '/contact',name: "Contact"}])}

我们可以获取我们页面当前的路由路径,并根据该路由显示一个模板。location.pathname返回页面的当前路由,我们可以将这段代码用于我们的 DOM:

let currentPath = window.location.pathname;if (currentPath === '/') {root.innerHTML = 'You are on Home page'} else {// check if route exist in the router instance let route = routerInstance.routes.filter(r => r.path === currentPath)[0];if (route) {root.innerHTML = `You are on the ${route.name} path`} else {root.innerHTML = `This route is not defined`}}

我们将使用该currentPath变量来检查路由实例中是否定义了路由。如果路由存在,我们将呈现一个简单的 HTML 模板。如果没有,我们将This route is not defined显示在页面上。

随意显示您选择的任何形式的错误。例如,如果路由不存在,您可以将其重定向回主页。

添加路由器链接

对于页面导航,我们可以添加路由器链接。就像使用Angular一样,您可以传递一个routerLink具有您要导航到的路径的值的值。为了实现这一点,让我们在index.html文件中添加一些链接:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><nav><button router-link="/">Home</button><button router-link="/about">About</button><button router-link="/contact">Contact</button><button router-link="/unknown">Error</button></nav><h1>Javascript Routing</h1><div id="app"></div><script src="main.js"></script>
</body>
</html>

注意我们传入的router-link属性——这是我们将用于路由的属性。

我们将创建一个存储所有的router-link变量并将其存储在一个数组中:

let definedRoutes = Array.from(document.querySelectorAll('[router-link]'));

在将我们的路由链接存储在一个数组中之后,我们可以遍历它们并添加一个调用navigate()函数的点击事件侦听器:

//iterate over all defined routesdefinedRoutes.forEach(route => {route.addEventListener('click', navigate, false)})

定义导航功能

导航功能将使用Javascript History API进行导航。history.pushState()方法将状态添加到浏览器的会话历史堆栈。

单击按钮时,我们将收到该按钮的路由器链接属性,然后使用history.pushState()导航到该路径,然后更改呈现的 HTML 模板:

  // method to navigatelet navigate = e => {let route = e.target.attributes[0].value;// redirect to the router instancelet routeInfo = routerInstance.routes.filter(r => r.path === route)[0]if (!routeInfo) {window.history.pushState({}, '', 'error')root.innerHTML = `This route is not Defined`} else {window.history.pushState({}, '', routeInfo.path)root.innerHTML = `You are on the ${routeInfo.name} path`}}

如果一个 nav 链接有一个未在 中定义的路由器链接routeInstance,它会将推送状态设置为This route is not Defined并在模板上error渲染。

接下来,您应该考虑将路由存储在单独的文件中,这样可以使代码更整洁,并且在出现任何错误时更易于调试。现在,创建routes.js文件并将路由构造函数和路由器实例提取到这个新文件中:

//router instance
let Router = function (name, routes) {return {name,routes}
};
let routerInstance = new Router('routerInstance', [{path: "/",name: "Root"},{path: '/about',name: "About"},{path: '/contact',name: "Contact"}
])export default routerInstance

导出此文件使其可供其他 JavaScript 文件访问。我们可以将它导入到我们的 main.js 文件中:

import routerInstance from './routes.js'

这将引发错误。要修复它,请将 index.html 文件中的脚本标记修改为:

<script type="module" src="main.js"></script>

添加模块的类型指定可以在模块外部访问哪些变量和函数。

结论

了解如何在 Vanilla JavaScript 中实现路由系统可以让开发人员更轻松地使用框架路由库,例如Vue.js 路由器。我们这里的代码可以在单页应用程序中重用,当您在没有框架的情况下工作时这是完美的。要获取源代码,请查看GitHub。

使用 History API 构建 JavaScript 路由器相关推荐

  1. 使用Acuity Scheduling的API构建在线课堂日历

    I moonlight (a lot of us do). I moonlight as a Lego Engineer. It's always been a dream of mine, and ...

  2. HTML5无刷新修改URL:利用 History API 无刷新更改地址栏

    为什么80%的码农都做不了架构师?>>>    HTML5 新增的历史记录 API 可以实现无刷新更改地址栏链接,配合 AJAX 可以做到无刷新跳转. 简单来说:假设当前页面为ren ...

  3. 「前端」History API与浏览器历史堆栈管理

    本文由尚妆前端开发工程师欲休撰写 本文发表于尚妆博客,欢迎订阅! 移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构.传统的单页应用基于url的hash ...

  4. react hooks使用_如何使用React Hooks和Context API构建简单的PokémonWeb App

    react hooks使用 After seven years of full stack development using Ruby, Python, and vanilla JavaScript ...

  5. ArcGIS API for javascript创建二维度地图

    1.引用arcgis api for javascript <link rel="stylesheet" href="https://js.arcgis.com/4 ...

  6. 使用 OpenAI API 构建 Next.js 应用程序的初学者指南

    欢迎阅读我们的初学者指南,了解如何使用 OpenAI API 构建 Next.js 应用程序.在本教程中,我们将引导您完成利用 OpenAI API 的功能创建功能强大且智能的 Next.js 应用程 ...

  7. darksky 经纬度_使用DarkSky API构建天气应用

    darksky 经纬度 网络构建几乎是每个人都可以享受到的乐趣,特别是当您使用API​​动态提取数据时. 有些人可能称其为"网页应用程序",有些人则称其为"网页" ...

  8. ArcGIS API for JavaScript——地图展示

    ArcGIS API for JavaScript 能够实现的最基本功能就是地图展示,包括地图缩放.平移.定位.实时显示坐标.展示地图要素(指北针.比例尺.图例).切换地图等.本文将详细介绍地图展示的 ...

  9. ArcGIS API for JavaScript 4.0尝鲜——WebGIS前端开发大杀器

    已经发布的ArcGIS API for JavaScript 4.0有着最前沿的新特性,这是一个更加对于开发者更加友好的Web API.3D的支持让你可以以更加炫酷的方式展示地理数据,而更加简洁明了的 ...

最新文章

  1. 从零开始学ios开发(十二):Table Views(中)UITableViewCell定制
  2. OVS datapath之action分析(十九)
  3. Python踩坑:类与类对象类型参数传递与使用
  4. SpringMVC实现文件的上传与下载
  5. 适合网页设计师的11个不错的Chrome插件
  6. 所有子序列的逆序对总和_一个数字的所有子串的总和
  7. 【Java】浅谈关键词transient的使用
  8. 系统学习NLP(八)--中文分词整理
  9. 微软的_tell函数实现
  10. 网管开始往ITSM迁移(第二季)
  11. linux网站5秒盾,宝塔面板建站后接入CF自动开启5秒盾证码脚本
  12. 【STM32开发环境搭建】 - st-link驱动安装和串口驱动安装
  13. StarRocks不稳定版本(解除AVX2指令集限制)
  14. python 自动下载网页链接_用python做一个网页自动下载脚本
  15. 广东地区经纬度Python版
  16. 水星路器服务器无响应,水星路由器无法上网怎么办?
  17. 操作系统--03内存管理
  18. 攻防世界 xctf wtc_rsa_bbq writeup
  19. KBEngine warring项目源码阅读(二) 登录和baseapp的负载均衡
  20. 应用于语义分割问题的深度学习技术综述(语义分割综述)

热门文章

  1. 今晚19:00,淘宝自研标准化协议库XQUIC开源直播!
  2. 宿舍管理系统-设计数据库
  3. linux启动jar后运行其他命令,Linux 部署jar 后台持续运行
  4. JDBC:JDBC工具类JDBCUtils
  5. Boosting三巨头:XGBoost、LightGBM和CatBoost(发展、原理、区别和联系,附代码和案例)
  6. 初判鸿蒙疏导通,八景探踪(山东卷)[6-03]
  7. 基于ssm应届毕业生在线职位管理平台
  8. 学术诚信的重要性_增强学术诚信意识,弘扬严谨学风
  9. Joan Ganz Cooney将接受IBC2018卓越国际荣誉奖
  10. 云原生周报 | 2021下半年CNCF开源项目发展总结;Cilium 1.11发布;BFE Server及控制面更新