如何为 SPA 创建普通 JS 路由?

2023-11-25

我正在创建一个没有框架/工具/库的网络应用程序,所有的都是 Vanilla JS。我的做法更像是“React”风格。

我想调用视图/pages/dashboard.js 中的视图,显示该视图并在用户单击仪表板导航链接时更改 URL。这是导航栏:https://codepen.io/Aurelian/pen/EGJvZW.

也许将子导航项集成到路线中会很好。如果用户位于个人资料的 GitHub 文件夹中,我将如何在 URL 中显示它?

我如何为此创建路由?

GitHub 存储库是https://github.com/AurelianSpodarec/JS_GitHub_Replica/tree/master/src/js

这是我尝试过的:

document.addEventListener("DOMContentLoaded", function() {
    var Router = function (name, routes) {
        return {
            name: name,
            routes: routes
        }
    };
    var view = document.getElementsByClassName('main-container');
    var myRouter = new Router('myRouter', [
        {
            path: '/',
            name: "Dahsboard"
        },
        {
            path: '/todo',
            name: "To-Do"
        },
        {
            path: '/calendar',
            name: "Calendar"
        }
    ]);
    var currentPath = window.location.pathname;
    if (currentPath === '/') {
        view.innerHTML = "You are on the Dashboard";
        console.log(view);
    } else {
        view.innerHTML = "you are not";
    }
});

制作香草 SPA 至少有两种基本方法。

哈希路由器

策略是添加一个监听器window.onhashchange(或者听哈希变化事件),每当 URL 中的哈希值发生变化时(例如,https://www.example.com/#/foo to https://www.example.com/#/bar。您可以解析window.location.hashstring来判断路由并注入相关内容。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div id="app"></div>
    <script>
      const nav = `<a href="/#/">Home</a> | 
                   <a href="/#/about">About</a> | 
                   <a href="/#/contact">Contact</a>`;
      const routes = {
        "": `<h1>Home</h1>${nav}<p>Welcome home!</p>`,
        "about": `<h1>About</h1>${nav}<p>This is a tiny SPA</p>`,
      };
      const render = path => {
        document.querySelector("#app")
          .innerHTML = routes[path.replace(/^#\//, "")] || `<h1>404</h1>${nav}`;
      };
      window.onhashchange = evt => render(window.location.hash);
      render(window.location.hash);
    </script>
  </body>
</html>

历史API

现代方法使用历史API这对用户来说更自然,因为 URL 中不涉及哈希字符。

我使用的策略是为所有同域链接点击添加事件侦听器。监听者调用window.history.pushState使用目标 URL。

“后退”浏览器事件被捕获popstate解析的事件window.location.href调用正确的路线。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div id="app"></div>
    <script>
      const nav = `<a href="/">Home</a> | 
                   <a href="/about">About</a> | 
                   <a href="/contact">Contact</a>`;
      const routes = {
        "/": `<h1>Home</h1>${nav}<p>Welcome home!</p>`,
        "/about": `<h1>About</h1>${nav}<p>This is a tiny SPA</p>`,
      };
      const render = path => {
        document.querySelector("#app")
          .innerHTML = routes[path] || `<h1>404</h1>${nav}`
        ;
        document.querySelectorAll('[href^="/"]').forEach(el => 
          el.addEventListener("click", evt => {
            evt.preventDefault();
            const {pathname: path} = new URL(evt.target.href);
            window.history.pushState({path}, path, path);
            render(path);
          })
        );
      };
      window.addEventListener("popstate", e =>
        render(new URL(window.location.href).pathname)
      );
      render("/");
    </script>
  </body>
</html>

上面的例子是尽可能少的。我有一个功能更全面的概念证明Glitch添加了基于组件的系统和模块。

如果你想处理更复杂的路线,route-parser包可以节省一些轮子的改造。

没有JS

顺便说一句,有一个技巧可以在没有 JS 的情况下制作基于哈希的 SPA,使用:target用于切换的 CSS 伪选择器display: none and display: block重叠的全屏部分,如中所述单个 HTML 文件中的整个网站 and https://john-doe.neocities.org.

html {
  height: 100%;
}
body {
  margin: 0;
  height: 100%;
}
section {
  padding: 1em;
  padding-top: 2em;
  display: none;
  position: absolute;
  width: 100%;
  height: 100%;
  background: #fff;
}
nav {
  padding: 1em;
  position: absolute;
  z-index: 99;
}
section:target {
  display: block;
}
#home {
  display: block;
}
<nav>
  <a href="#">Home</a> |
  <a href="#about">About</a> |
  <a href="#contact">Contact</a>
</nav>
<section id="home">
  <h1>Home</h1>
  <p>Welcome home!</p>
</section>
<section id="about">
  <h1>About</h1>
  <p>This is a tiny SPA</p>
</section>
<section id="contact">
  <h1>Contact</h1>
  <p>Contact page</p>
</section>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为 SPA 创建普通 JS 路由? 的相关文章

  • 如何在 Highcharts / Highstock 上显示 x 轴上的十字线选定值和 y 轴上选定的日期?

    我正在研究这个项目 其中包括在交互式图表上显示历史数据 我得出的结论是 Highcharts Highstock 是最好的选择 因为它提供了最多的定制选项 我想要实现的目标是 当我将鼠标悬停在一个点上时 分别在 x 轴和 y 轴上显示所选值
  • javascript中怪异模式的元素宽度?

    我一直在浏览所有流行的 js 库 但我找不到一个具有 DOM 元素宽度函数的库 该函数实际上可以解释 Internet Explorer 中的怪异模式 问题是 当启用怪异模式时 填充和边框不会计入宽度 据我所知 当省略 doctype 或将
  • 在淘汰赛应用程序中使用 setInterval 进行轮询实现?

    我正在尝试使用 setInterval 实现简单的轮询机制 我有一个视图模型如下 define knockout jquery function ko function ViewModel var self this setInterval
  • 错误找不到“pages”目录。请在项目根目录下创建一个”

    以前我的项目设置是 public next src pages components assets next config js 这工作正常 但我将结构更改为以下 public src client next config js jscon
  • React JS - 单击时更改颜色并将默认颜色放在所有其他颜色上

    我有 x 个渲染数文章预览依赖于 API 调用的组件 div div Object keys images map index i gt return div div
  • Child_process 处理带有回车符 (\r) 的 STDOUT 流

    我正在编写一个简单的应用程序 它允许工作中的内部系统请求从远程服务器到使用 REST 调用发起的另一个远程服务器的复制过程 使用 rsync 我已经对express框架足够熟悉 并且刚刚开始尝试child process库 并偶然发现了一个
  • Office excel将CORS请求作为跨域请求

    我正在尝试从我的 Excel 插件发出跨域请求 正如这里所建议的 http dev office com docs add ins develop addressing same origin policy limitations http
  • 使用 javascript 禁用按钮:FF 与 IE

    我有一排按钮 它们都会创建一个我想在新选项卡中打开的 pdf 文件 这样按钮页面就会保持在顶部 并且 pdf 会打开以进行打印 为了防止单击按钮两次 我禁用该按钮 如下所示 我使用 python
  • Ajax JSON 数据和灯箱冲突

    我有一个带有灯箱插件的画廊设置光廊 http sachinchoolur github io lightGallery docs 该画廊与静态 HTML 完美配合 当我动态抓取 API 数据并尝试让灯箱处理这些项目时 问题就出现了 我似乎无
  • mouseover 和 mouseout 事件在子进程上触发

    代码 div div div div 如果我将鼠标悬停在Navigation the Drop Downdiv 向下滑动 如果我将鼠标移开 它会向上滑动 问题是如果我将鼠标悬停在孩子上Drop Downdiv它也向上滑 动 有谁知道我该如何
  • Angular 2 runOutsideAngular 仍然改变 UI

    从我的理解来看runOutsideAngular https angular io docs ts latest api core index NgZone class html runOutsideAngular anchor 如果我需要
  • 在overlayImage中应用滤镜的方法在哪里?

    我想在overlayImage中应用一个过滤器 唯一的方法是在渲染后在整个画布上应用过滤器 对此没有内置支持 但很容易 破解 var overlayImageUrl load overlay image first fabric Image
  • 使用本机 JavaScript 获取过渡中的 CSS 值

    这个问题之前被问过 但答案使用了 jQuery here https stackoverflow com q 8920934 3186555 因此 我将调整问题以专门询问native解决方案 to 最小化依赖关系 假设您有一个 div 然后
  • React + Semantic-UI:在 UI MODAL 中使用表单

    在没有 React 的普通旧 Semantic UI 中 我已经能够毫无问题地将表单放入 Modal 中 使用 Semantic UI React 版本 我能够在模态中显示表单 但它并没有按照我期望的方式工作 例如 模态框显示后 模态框内的
  • 水平平滑滚动 100px

    Heyjo problem 一周以来我一直在寻找 javascript 或 jQuery 代码 以便在我的网站上实现滚动按钮 我失败的那一刻是按钮应该多次工作的时候 他的任务不是滚动到专用元素 而是应该向左滚动 例如 100px 此外 滚动
  • 限制 jQuery id 字符串吗?

    简而言之 我的问题是字符串在 jQuery 中作为可搜索 id 或可搜索内容有什么限制 更新 我得到了 ID 部分 但不是为什么我什至无法使用该字符串搜索 html 内容 对于任何愿意告诉我一个正则表达式来将模式从 MM dd yy HH
  • ExpressJS - DELETE 请求后 res.redirect

    我一直在寻找如何执行此操作 我正在尝试在发出删除请求后重定向 这是我正在使用的代码没有重定向 exports remove function req res var postId req params id Post remove id p
  • javascript:window.print() 打印 2 页,而我有 1 页

    我有一个简单的 HTML 文档 其中仅包含图像标签 我想在文档加载后打印图像 我的代码 img src form1 jpg alt form1 style margin 0 auto display block 它可以工作 但问题是它打印图
  • 如何按字母顺序排序并先小写排序

    如何获得以下排序的结果Food to Eat然后是 食物123 显然 第二个较低的 o 应该将 要吃的食物 带到排序后的第一个项目中 我很惊讶这个问题不容易通过谷歌找到答案 这个壮举没有包含在 javascript 标准中也让我感到惊讶 F
  • 更改javascript nodejs中所有页面的href url

    我已经实现了具有多种语言下拉菜单的引导导航栏 当我选择语言时 它将翻译页面 如何更改其他页面的 url 和按钮文本 当我选择french 将所有网址更改为 fr about and fr contact 如何使用 JavaScript 进行

随机推荐

  • QT 中的 64 位 int Spin Box

    我正在构建一个 Windows 程序 该程序应具有 64 位数值的控件 这些控件应可切换为签名或未签名 我发现了两个控件 旋转盒 int32 和 双旋转盒 double 使用 double 我可以覆盖范围 但它无法处理精度 有没有办法改变这
  • 如何在React项目中隐藏chart.js中的图例?

    我试图隐藏使用 Chart js 创建的图表的图例 根据官方文档 https www chartjs org docs latest configuration legend html 隐藏图例 display的财产options disp
  • 如何检查是否已定义 angularjs 控制器

    我有一个这样定义的应用程序 angular module myApp config function stateProvider controllerProvider if isControllerDefined controllerNam
  • 是否可以将 Xdebug 与内置 PHP 测试服务器一起使用?

    基本上我的问题说明了一切 我希望能够检查脚本变量的状态 设置断点等 而无需安装 Nginx apache 或 PHP FPM 这是否可行 如果不可行我的选择是什么 好吧 所以分手了本文我已经成功使用xdebug 我使用自制程序在 Mac O
  • 如何在 Cocoa Objective-C 中将文本转换为图像

    我正在寻找一种在 Cocoa 中将一段文本转换为图像的方法 一切似乎都描述了将图像转换为文本 而不是文本转换为图像 简单地说 我想取一个单词 例如 Kevin 并将其转换为位图图像进行操作并保存为 JPEG 给出答案的人都很棒 感谢您提供三
  • 无法将 Spring 应用程序部署到 Websphere

    我在开发阶段一直在开发 tomcat 的应用程序 随着我们的进展 我的客户希望部署到 websphere 我试图在 websphere 8 5 上这样做 但由于某种原因我似乎遇到了问题 Tomcat 很简单 我只是加入了战争 一切都按预期进
  • 设置连接到 Web 音频 api 的音频元素的playbackRate

    我一直在尝试使用 createMediaElementSource 将音频元素连接到网络音频 api 并让它工作 但我需要做的一件事是更改音频标签的播放速率 但我无法让它工作 如果您尝试运行下面的代码 您会发现它一直有效 直到您取消注释我们
  • Android - 工具栏标题居中[重复]

    这个问题在这里已经有答案了 我的应用程序中有一个工具栏 如下所示
  • 如何从文件的字节数组中获取文件名?

    我有代表我通过网络传输的文件的字节 除了在文件系统上手动重建文件外 如何从文件中获取信息 例如getName getPath 等 换句话说 我从机器 A 上的一个文件开始 我使用 FileUtils 将文件转换为字节数组 我通过网络将该文件
  • python 字节码兼容性

    python 字节码在不同版本之间的兼容性程度如何 我不是在谈论 python2 x 到 python3 x 而是说 Python33 到 python34 我并不是为了 安全 而追求它 我使用 Cython 将程序的大部分转换为 C 但是
  • 拉动刷新并加载更多列表视图,如 facebook [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 here i am using sliding drawer in that on click home icon it shows 3 tabs 1 which concept
  • 在 Java 中验证 PKCS#7 证书

    需要一些有关 Java 加密例程的帮助 给定 PKCS 7 签名 我想根据受信任的存储验证它包含的所有证书 我假设签名中包含的所有证书都按正确的顺序形成有效的证书路径 或链 等等 以便 最上面 0 是签名证书 下一个 1 是中间证书 用于签
  • 无法安装 RMagick 2.13.1。找不到 MagicWand.h。

    当我尝试安装 rmagick 时 出现以下错误消息 Can t install RMagick 2 13 1 Can t find MagickWand h extconf rb failed Could not create Makefi
  • “清除内存”后小部件不工作

    问题是 在我使用内置任务管理器的清理内存 RAM后 我的小部件停止工作 我想这与任务管理器清理RAM的方法有关 经过大量研究和尝试 我发现我需要 BroadcastReciever 用于监听包的更改和更新 所以我实现了 但它不起作用 因为文
  • JQgrid - 在搜索选项中转义“:”(值部分)

    这里解释了如何设置过滤器的值链接文本 我有两个要求 1 默认值需要为空 我预计 如果未设置 defaultValue 则过滤器为空 但在我的情况下不会发生这种情况 2 如何转义我的值中的 字符 和 用于分隔索引和值 但是 在我的值字符串中
  • Ace Editor - 更改 CTRL+H 键绑定

    I m working on an implementation of Ace Editor and Ctrl F works great for the built in Find dialog however I m trying to
  • Android Studio:构建 APK 与运行 APK 之间的大小差异

    我注意到使用这两个选项生成的 apk 的大小存在差异 为什么会发生这种情况 随着构建 gt 构建 APK option MyProject app build outputs apk app debug apk 大小 2 997 KB 随着
  • 将 ActionView::Helpers::FormBuilder 传递给部分

    我正在尝试根据特定的 AJAX 请求动态创建表单元素 这是我的设置 View div div 控制器 def check unique id student Student new this form ActionView Helpers
  • Nginx反向代理导致无限循环

    我的 Nginx 站点配置文件中有以下内容 server listen 80 default server listen 80 default server ipv6only on root usr share nginx html ind
  • 如何为 SPA 创建普通 JS 路由?

    我正在创建一个没有框架 工具 库的网络应用程序 所有的都是 Vanilla JS 我的做法更像是 React 风格 我想调用视图 pages dashboard js 中的视图 显示该视图并在用户单击仪表板导航链接时更改 URL 这是导航栏