欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-17 16:20:03
前言当你想到路由时,通常会想到类似react之类的库。但实际上,这些库和框架仍然使用vanillajavascript。那么该怎么实现呢?我希望这个“javascript路由教程”能够帮你了解如何用原...

前言

当你想到路由时,通常会想到类似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路由的资料请关注其它相关文章!

相关标签: JS 原生 路由