如何制作自己的原生JavaScript路由


Posted in Javascript onMay 05, 2021

前言

当你想到路由时,通常会想到类似react之类的库。但实际上,这些库和框架仍然使用vanillaJavaScript。那么该怎么实现呢?

我希望这个“JavaScript路由教程”能够帮你了解如何用原生js写出自己的路由。

简介

我遇到了很多出于各种原因想要自己创建路由的人。既然你看到本文,那意味着你可能也是其中的一个!

最重要的是,使用vanillajsrouter可以减少你对框架的依赖。

只要你了解实现它所涉及的所有部分,就可以相对容易的在原生 JavaScript 中创建自己的路由。

以下是制作自己的JS router时要了解的关键事项:

1.原生 JS 路由的关键是location.pathname属性。

2.侦听 “popstate”事件以响应.pathname的更改。每当在浏览器的地址栏中输入新的 URL,但我们不想刷新页面时,就会发生这种情况,我们只是想通过加载新内容来刷新视图。

3.你可以选择将路由存储在routes[]数组中。

4.必须用JavaScript 正则表达式(RegEx)才能解析 URL。

5.如果希望将路由集成到本机浏览器体系结构中,那么对history和history.pushState(JavaScript 的 History API)的基本了解至关重要。

首先,我们将处理 History API。

JavaScript 的 History API

我看过很多没有提到 JavaScript History API 的vanilla JS router教程。太糟糕了,因为单击浏览器的“后退”和“前进”按钮与浏览历史记录中的 URL 导航有关。如果没有 History API,就无法谈论路由。

1.history.back()与history.go(-1)相同,或者当用户在浏览器中单击Back按钮时。你可以用任何一种方法达到相同的效果。

2.当用户按下浏览器的Forward按钮时,将执行history.forward(),它等效于history.go(1)”。

3.go()与.back()和forward()方法相似,不同之处在于你可以指定浏览器历史记录栈中要前进或后退的步数。 。

4.pushState()会将新状态推送到 History API。

5..length属性是会话历史记录中的元素数。

6..state属性用于查找状态,而无需侦听“ popstate”事件。

实现自己的原生JS路由

基于 History API 的 Vanilla JS 路由设置

先让我们仔细研究构建 URL 切换器所需的最少代码(而无需刷新页面),然后我会向你展示其的工作方式的 GIF 动图。

<html>
    <head>
        <title>Hello</title>
        <script type = "module">
            function select_tab(id) {
                // remove selected class from all buttons
                document.querySelectorAll(".route").forEach(item => item.classList.remove('selected'));
                // select clicked element (visually)
                document.querySelectorAll("#" + id).forEach(item => item.classList.add('selected'));
            }
            function load_content(id) {
                // Update text "Content loading for {id}..."
                // Of course, here you would do you content loading magic
                // Perhaps run Fetch API to update resources
                document.querySelector("#content").innerHTML = 'Content loading for /' + id + '...';
            }
            function push(event) {
                // Get id attribute of the box or button or link clicked
                let id = event.target.id;
                // Visually select the clicked button/tab/box
                select_tab(id);
                // Update Title in Window's Tab
                document.title = id;
                // Load content for this tab/page
                loadContent(id);
                // Finally push state change to the address bar
                window.history.pushState({id}, `${id}`, `/page/${id}`);
            }
            window.onload = event => {
                // Add history push() event when boxes are clicked
                window["home"].addEventListener("click", event => push(event))
                window["about"].addEventListener("click", event => push(event))
                window["gallery"].addEventListener("click", event => push(event))
                window["contact"].addEventListener("click", event => push(event))
                window["help"].addEventListener("click", event => push(event))
            }
            // Listen for PopStateEvent (Back or Forward buttons are clicked)
            window.addEventListener("popstate", event => {
                // Grab the history state id
                let stateId = event.state.id;
                // Show clicked id in console (just for fun)
                console.log("stateId = ", stateId);
                // Visually select the clicked button/tab/box
                select_tab(stateId);
                // Load content for this tab/page
                loadContent(id);
            });
        </script>
        <style>
            * { /* global font */
                font-family: Verdana;
                font-size: 18px;
            }
            #root { display: flex; flex-direction: row; }
            #content { display: flex;
                display: block;
                width: 800px;
                height: 250px;
                /* vertically centered text */
                line-height: 250px;
                border: 2px solid #555;
                margin: 32px;
                text-align: center;
            }
            .route {
                cursor: pointer;
                justify-content: center;
                width: 150px;
                height: 50px;
                /* vertically centered text */
                line-height: 50px;
                position: relative;
                border: 2px solid #555;
                background: white;
                text-align: center;
                margin: 16px;
            }
            .route.selected { background: yellow; }
        </style>
    </head>

    <body>

        <section id = "root">
            <section class = "route" id = "home">/home</section>
            <section class = "route" id = "about">/about</section>
            <section class = "route" id = "gallery">/gallery</section>
            <section class = "route" id = "contact">/contact</section>
            <section class = "route" id = "help">/help</section>
        </section>

        <main id = "content">Content loading...</main>
    
    </body>

</html>

核心是对的window.history.pushState({id}, ${id}, /page/${id});调用;

第一个参数是状态的唯一 ID,第二个是“标签标题”文本,第三个参数是你希望地址栏中要现实的路径。这就是使浏览器无需重新加载页面即可更改 URL 的原因。

结果。现在,每次我们单击按钮时,URL实际上都会在浏览器的地址栏中更改。内容框也会更新。

我们的原生 JS 路由开始运行了。请注意,每次单击按钮时,history.pushState 被触发。我们只需将存储在元素的 id 属性中的 clicked 元素的 id 传递给它即可:home,about,gallery等。它们应与你要导航到的实际页面一致。当然这不是存储页面名称的唯一方法,例如可以用 array [] 或其他任何方式。这就是本例中的操作方式。

当然我们还需要从服务器加载有关该位置的布局和资源的内容。这取决于你的程序。可以是任何东西。

使“后退”和“前进”按钮起作用

通过使用history.pushState,你将自动使Back和Forward按钮导航到上一个或下一个状态。这样做会产生popstate事件。这是你必须再次更新视图的部分。 (第一次是我们单击按钮时。)

但是由于该事件带有单击的id,因此单击Back或Forward时很容易刷新视图并重新加载内容。

我们在这里没有使用react或vue,因此在我的源代码中load_content将负责直接在 DOM 中更新视图。此区域可能填充了你的 API 加载的某些内容。由于这只是“前端”示例,因此我无法向你展示太多内容。但这就是它在客户端上的工作方式。

初始化服务器端的路由负载

将它们放在一起还需要再执行一个步骤。在我的例子中,只用了router.html。当你第一次在 PWA 中加载此路由时,必须确保如果直接在地址栏中输入/page/home时,它可以工作。

到目前为止,我们仅从前端更改了路由器地址。假定每次你导航到出现在路由按钮上的 URL 时,实际上都会从服务器单独加载该 URL。

因此你有责任确保/page/about将路由器和页面的加载到应用程序的根视图中。它还应突出显示“current”按钮。

实施完毕后,你的路由就完成了。你如何选择重新加载#content元素中的内容完全取决于你自己和你的后端设计。

以上就是如何制作自己的原生JavaScript路由的详细内容,更多关于制作原生JavaScript路由的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JavaScript高级程序设计 阅读笔记(七) ECMAScript中的语句
Feb 27 Javascript
jquery 利用show和hidden实现级联菜单示例代码
Aug 09 Javascript
JavaScript中判断整数的多种方法总结
Nov 08 Javascript
JavaScript实现三阶幻方算法谜题解答
Dec 29 Javascript
javascript实现在线客服效果
Jul 15 Javascript
javascript动态添加checkbox复选框的方法
Dec 23 Javascript
Linux下为Node.js程序配置MySQL或Oracle数据库的方法
Mar 19 Javascript
javascript 判断一个对象为数组的方法
May 03 Javascript
JavaScript继承与多继承实例分析
May 26 Javascript
微信小程序常用简易小函数总结
Feb 01 Javascript
转换layUI的数据表格中的日期格式方法
Sep 19 Javascript
Vue + iView实现Excel上传功能的完整代码
Jun 22 Vue.js
Vue项目中如何封装axios(统一管理http请求)
May 02 #Vue.js
如何用JavaScript学习算法复杂度
JS不要再到处使用绝对等于运算符了
Apr 30 #Javascript
如何用Node.js编写内存效率高的应用程序
用几道面试题来看JavaScript执行机制
Apr 30 #Javascript
详解前端任务构建利器Gulp.js使用指南
Apr 30 #Javascript
浅谈node.js中间件有哪些类型
Apr 29 #Javascript
You might like
PHP的开合式多级菜单程序
2006/10/09 PHP
php实现mysql数据库分表分段备份
2015/06/18 PHP
PHP实现二维数组按某列进行排序的方法
2016/11/18 PHP
Js日期选择器并自动加入到输入框中示例代码
2013/08/02 Javascript
微信JS接口汇总及使用详解
2015/01/09 Javascript
javascript实现淡蓝色的鼠标拖动选择框实例
2015/05/09 Javascript
JavaScript实现带播放列表的音乐播放器实例分享
2016/03/07 Javascript
基于JS实现导航条flash导航条
2016/06/17 Javascript
AngularJS ng-bind 指令简单实现
2016/07/30 Javascript
jquery实现限制textarea输入字数的方法
2017/09/06 jQuery
Node调用Java的示例代码
2017/09/20 Javascript
详解VUE中常用的几种import(模块、文件)引入方式
2018/07/03 Javascript
微信小程序实现天气预报功能
2018/07/18 Javascript
JavaScript事件发布/订阅模式原理与用法分析
2018/08/21 Javascript
小程序实现左右来回滚动字幕效果
2018/12/28 Javascript
D3.js(v3)+react 实现带坐标与比例尺的散点图 (V3版本)
2019/05/09 Javascript
js简单遍历获取对象中的属性值的方法示例
2019/06/19 Javascript
Node.JS枚举统计当前文件夹和子目录下所有代码文件行数
2019/08/23 Javascript
Python的爬虫框架scrapy用21行代码写一个爬虫
2017/04/24 Python
Python3实现简单可学习的手写体识别(实例讲解)
2017/10/21 Python
python-docx修改已存在的Word文档的表格的字体格式方法
2018/05/08 Python
Pycharm 设置默认解释器路径和编码格式的操作
2021/02/05 Python
各大浏览器 CSS3 和 HTML5 兼容速查表 图文
2010/04/01 HTML / CSS
英国领先品牌手动工具和电动工具供应商:Tooled Up
2018/11/24 全球购物
澳大利亚珠宝商:Shiels
2019/10/06 全球购物
运动鞋、街头服装、手表和手袋的实时市场:StockX
2020/11/25 全球购物
研究生自我鉴定范文
2013/10/30 职场文书
学年末自我鉴定
2014/01/21 职场文书
2014庆六一活动方案
2014/03/02 职场文书
青少年法制教育心得体会
2016/01/14 职场文书
同学联谊会邀请函
2019/06/24 职场文书
青年人初次创业的“五不要”
2019/08/23 职场文书
导游词之井冈山
2019/11/20 职场文书
Pytest allure 命令行参数的使用
2021/04/18 Python
pytorch 实现在测试的时候启用dropout
2021/05/27 Python
Java8中接口的新特性使用指南
2021/11/01 Java/Android