我看到一篇关于如何在纯 Vanilla JavaScript 中创建路由器的帖子。由于它不是在讨论散列路由,因此我决定创建这篇文章来与您分享我的知识。

我为什么要这么做?

多亏了 History API,在 JavaScript 中构建路由器现在变得很简单。它在很大程度上得到支持,让您可以按照自己的方式构建路由器,而无需依赖第三方库。在 Vue.js 中,您甚至可以构建自己的自制路由器并将其插入,这要归功于 Vue.js 插件。事实上,Vue.js 的官方路由器库 Vue Router 依赖于 History API。但不仅如此。因为它可以选择让您构建所谓的散列路由器。

什么是散列路由器?

它是一个不依赖 History API 而是依赖于您网站的哈希 URL 的路由器。假设您的网页上有一个标题。

<h2>About me</h2>
<p>Lorem ipsum dolor sit amet...</p>

并且您希望您的用户在页面顶部时直接跳转到此部分。你会想id为你的标题使用一个属性。

<h2 id="about">About me</h2>

并创建一个链接,例如在您的标题中,将您的用户重定向到此部分。

<header><a href="#about">About me</a>
</header>

现在,如果您单击链接,URL 应该来自

http://yoursite.com

http://yoursite.com#about

没什么花哨的,对吧?

为什么我要使用散列路由器?

基于历史 API 的路由器的问题在于它依赖于页面的来源来工作。如果您尝试打开实现 History API 的 HTML 页面,您应该会看到如下内容:

Failed to execute 'pushState' on 'History': A history state object with URL 'file:///path/to/index.html' cannot be created in a document with origin 'null'

这是因为默认情况下,作为文件打开的 HTML 文档的来源设置为null. 这是个问题。

相反,基于 hased 的路由器不依赖于它,而是依赖于窗口对象触发的事件。当我们更改 url 的哈希时,将触发此事件。在我们之前的示例中,单击链接会触发此事件。不需要网络服务器。

如何实现散列路由器?

它就像只使用一个事件一样简单。事件onHashChange。

<!DOCTYPE html>
<html><body><a href="#home">Home</a><a href="#about">About</a><script src="script.js"></script></body>
</html>
function onRouteChanged() {console.log("Hash changed!");
}window.addEventListener("hashchange", onRouteChanged);
Hash changed!
Hash changed!

在线尝试。

实现路由

我们现在需要获取用户发出的路由。我们可以使用该window.location.hash属性来获取当前“路线”的值。

function onRouteChanged() {console.log(window.location.hash);}
#home
#about

在线尝试。

我们现在拥有我们需要的一切。我们可以开始为我们的路由器实现视图渲染器。

      <a href="#about">About</a><a href="#contact">Contact</a><main id="router-view"></main><script src="script.js"></script>

我还添加了另一个链接。这将帮助我向您展示我们如何实现404 - page not found处理程序。你会惊讶于它是多么容易。

接下来,我们需要向我们的处理程序添加更多逻辑,onRouteChange以便它可以像路由器一样呈现我们的路由。

function onRouteChanged() {const hash = window.location.hash;const routerView = document.getElementById("router-view");if (!(routerView instanceof HTMLElement)) {throw new ReferenceError("No router view element available for rendering");}switch (hash) {case "#home":routerView.innerHTML = "<h1>Home page</h1>";break;case "#about":routerView.innerHTML = "<h1>About page</h1>";break;default:routerView.innerHTML = "<h1>404 - Page Not Found</h1>";break;}
}

在线尝试。

我将哈希 URL 存储在一个变量中,以便我可以使用该switch语句根据用户发出的路由呈现不同的 HTML 内容。我还存储了路由器视图元素以检查该元素是否确实在文档中(我们永远不知道会发生什么,在这种情况下有一些雄辩的错误消息会很好)。我还需要它来更新语句innerHTML中路由器的内容。switch

switch 的默认语句将通过我们的联系链接触发,因为我们没有在 switch 中为它指定任何处理程序。

而已!您有一个非常基本的路由器,可以在任何地方工作,无论是托管在 Web 服务器上,还是作为单个 HTML 页面共享。例如,当您需要向客户展示网站的快速原型时,我可以看到一些用例。他所要做的就是在他的浏览器中打开页面,然后tada!

限制

当然,这种路由有一个明显的限制,因为我们使用的是 URL 的哈希值,并破解了它的初衷,将其用作路由器。但是如果我们需要在我们的页面中使用常规的hrefs,它只会破坏路由,因为它会触发我们的哈希更改处理程序。

解决方案

我为这个问题找到的一个解决方案可能不是最好的,但如果你绝对需要使用基于散列的路由,那么它是值得的,它是使用data-*属性和一点 JavaScript。

<button data-go-to-id="a-little-introduction">to the intro</button>
<!-- later in the document -->
<h2 id="a-little-introduction>A little introduction</h2>
"use strict";document.querySelectorAll("[data-go-to-id]").forEach(function(link) {link.addEventListener("click", function() {const element = document.getElementById(link.dataset.goToId);if (!(element instanceof HTMLElement)) {throw new ReferenceError(`Unable to found element with id "${goToId}"`);}window.scroll({top: element.getBoundingClientRect().top,left: 0,behavior: "smooth"});});
});

某些设备上的平滑滚动不起作用(我特别想到了一些 Apple 设备),但我敢肯定,这将是您可以找到解决此问题的许多解决方案之一。我的解决方案的缺点是它不能用于共享链接,如Hey, look what I found here: http://yoursite.com#home#title-of-article. 我将此作为练习,供读者实施更好的解决方案。

结论

基于哈希的路由器是另一种无需重新加载页面即可路由用户的方式。这在创建 GitHub 页面时也很方便,因为我们不必重新考虑基于历史记录的路由器并在所有路由前加上/github-repo/about.

如果您不需要使用大量的 href 重定向并且不想/不能使用 History API,那么在您的页面中使用路由器可能是一个很好的解决方案。

我向您展示的是基于 hased 的路由器的一个非常基本的实现。如果你想更进一步,你可以:

  • 在一个对象中实现这个路由器,就像new HashedRouter使 API 更易于使用一样。addRoute特别是使用和之类的方法start
  • 找到比我用来在页面中实现链接更好的解决方案。
'use strict';function onRouteChanged() {const hash = window.location.hash,routerView = document.querySelector('#router-view');if (!(routerView instanceof(HTMLElement))) {throw new ReferenceError('No router view element available for rendering');}switch (hash) {case '#home':routerView.innerHTML = '<object type="text/html" data="views/home.html"></object>';break;case '#about':routerView.innerHTML = '<object type="text/html" data="views/about.html"></object>';break;default:routerView.innerHTML = '<object type="text/html" data="views/404.html"></object>';break;}//console.log(hash);
}window.addEventListener('hashchange', onRouteChanged);

Vanilla JavaScript 哈希 URL 路由器相关推荐

  1. 使用 Vanilla JavaScript 构建自定义 SPA 路由器

    介绍 在本文中,我将解释如何使用 Vanilla JavaScript 构建自定义 SPA 路由器.我必须在没有任何使用框架的情况下构建一个 UI 项目,并且必须弄清楚如何处理路由,并发现您可以轻松地 ...

  2. 取出url中的字符_如何在JavaScript中解析URL:例如主机名,路径名,查询,哈希?...

    统一资源定位符(缩写URL)是对Web资源(网页,图像,文件)的引用.URL指定资源位置和检索资源的机制(http,ftp,mailto). 例如,这是此博客文章的URL: 通常,您需要访问URL的特 ...

  3. vanilla_使用Vanilla JavaScript即时搜索

    vanilla Originally posted on www.florin-pop.com 最初发布在www.florin-pop.com The theme for week #15 of th ...

  4. 使用 Vanilla JavaScript 框架创建一个简单的天气应用

    大家好,不知道大家听说过 Vanilla JavaScript 这款框架吗?最近我在浏览国外的一些技术网站时,这个词出现的频率实在是太高了,好多框架都宣称自己是基于 Vanilla JavaScrip ...

  5. vanilla_如何在Vanilla JavaScript中操作DOM

    vanilla by carlos da costa 通过卡洛斯·达·科斯塔 如何在Vanilla JavaScript中操作DOM (How to manipulate the DOM in Van ...

  6. vanilla_包装Vanilla JavaScript软件包以在React中使用

    vanilla Complex web projects often require the use of 3rd party widgets. But what if you're using a ...

  7. 如何使用Bootstrap 5从jQuery切换到Vanilla JavaScript

    Bootstrap 5 is a free and open-source CSS framework directed at responsive, mobile-first front-end w ...

  8. 使用 Vanilla JavaScript 创建 Web 组件

    Web 应用程序开发是一个非常拥挤的技术领域.有不同类型的框架.库和工具.在开发 Web 应用程序时,主要目标是提供带有封装组件的高质量用户界面 (UI). 因此,当您使用 React.Vue.Ang ...

  9. Vanilla JavaScript 和 Vue 中的 HTML <template>标签

    HTML Template Tag in Vanilla JavaScript and Vue - DEV Communityhttps://dev.to/therealdanvega/html-te ...

最新文章

  1. Share Point 2013使用Windows PowerShell 获取,删除UserProFile
  2. [YTU]_2916(Shape系列-2)
  3. 【神经网络架构】Pyramidal Convlution(PyConv):金字塔卷积,“即插即用“,提升你的网络性能
  4. Ribbon-饥饿加载
  5. 使用Kubernetes和Docker将Spring Boot与MongoDB作为容器部署
  6. 一文带你了解人工智能最新进展:AI从业者如何选择技术路线?
  7. H3C中标苏州教育城域网改造项目
  8. PAT (Basic Level) Practice1023 组个最小数
  9. ubuntu18.04窗口截图和选区截图快捷键
  10. Ubuntu安装gcc-7.3.0
  11. 2016matlab打开toolbox,MATLAB2016添加工具箱toolbox方法,有截图
  12. 可以使用python开发财务软件吗_给还准备继续做审计的人提个醒!
  13. pacman 查询_Pacman 命令记录
  14. 大数字加法运算(超过1000位)
  15. mplayer-2.3节:视频输出设备 .
  16. 分析师不死心 仍坚信微软终将成功并购雅虎
  17. 【微信支付付款至零钱】
  18. 红红火火恍恍惚惚(bfs_plus.2)(知道吉米你很急!)
  19. word文档加密经验实战分享
  20. 【优化求解】基于蝗虫算法求解单目标问题附matlab代码

热门文章

  1. Python skimage快速图像处理(二)——Numpy速成
  2. 2020-1-17数字逻辑于数字系统课程实验一(门电路逻辑功能及测试)
  3. 全栈开发工程师面试题一
  4. excel学习——相对引用、绝对引用、混合引用
  5. 打起来了,打起来了!!
  6. 判断两个无环单向链表/有环单向链表是否相交,并返回相交节点
  7. 伤寒杂病论.辨太阳病脉证并治(下)
  8. 附录1 标准Job-shop Benchmark问题数据集最优解(续2)
  9. (附源码)spring boot信佳玩具有限公司仓库管理系统 毕业设计 011553
  10. (MBI)Pt(acac)|(PBI)_2Pt|(t-BuPBIM)_2Pt铂配合物的空间构型