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

更新日期: 2019-12-30阅读: 2.3k标签: 路由

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

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


简介

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

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

只要你了解实现它所涉及的所有部分,就可以相对容易的在原生 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 路由!

我将简单地对的 htmlcss 和 JavaScript 进行注释。


基于 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 传递给它即可:homeaboutgallery 等。它们应与你要导航到的实际页面一致。当然这不是存储页面名称的唯一方法,例如可以用 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 元素中的内容完全取决于你自己和你的后端设计。


链接: https://fly63.com/article/detial/8461

vue路由history模式_如何去除vue项目中的#

在使用vue-cli搭建的环境中,浏览器上URL地址中是存在#的,这是由于vue-router 默认 hash 模式,不难发现#的出现真的很丑陋。官网给出了如何使用history模式mode: history

vue路由传参主要的3种方式

vue中路由传参主要的3种方式:query方式(push时使用path来匹配)、params模式(push时使用name来匹配)、location预声明参数模式(push使用path来匹配,但是它跟params模式不同)

vue动态加载路由_实现vue动态加载路由器设置

我们的通用的后台管理系统中,我们会根据权限的粗细不同,会对每个角色每个权限每个资源进行控制。同样的我们也需要实现一个这样的功能。 这篇文章我将主要讲vue端的实现,关于后台接口我就不会涉及,当我接触的时候我们的后台接口是springcloud实现。

两种前端路由的实现方式

前后端分离开发模式,后端会把路由控制丢在前端,这几天再开发单页面小的项目,手动撸了个路由。前端路由实现有两种方法。HTML5 History API包括2个方法:history.pushState()和history.replaceState(),和1个事件:window.onpopstate。hash + location.onhashchange

vue动态路由_vue-router通过接口请求动态生成路由的实现

在后台管理系统中,一般都会采用权限管理。路由菜单数据都会保存到数据库中,在vue-router 2.2版本新增了一个router.addRoutes(routes)方法,即可用它来实现动态路由了

HTML5 History 模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

vue router 路由鉴权(非动态路由)

原本想用动态路由的思路去做,按权限加载对应路由表,但是由于权限可以交叉(比如一个人可以同时是主题管理员和数据服务管理员),导致权限路由表还是得去做判断组合。于是放弃了这个思路,索性就在beforeEach里直接判断了。

vue中路由按需加载的几种方式

使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,webpack在打包的时候会把整个路由打包成一个js文件,如果页面一多,会导致这个文件非常大,加载缓慢

vue-router 中参数传递(params,query)

query和params的区别,query相当于get请求,在页面跳转的时候,可以在地址栏看到请求参数,然而params则相当于post请求,参数不会在地址栏中显示。

Node.js的路由

当服务端接收到HTTP请求时,可以通过onRequest() 获取到url, pathname,query,及paramParams参数;为了解析这些数据需要使用url和querystring模块

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!