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


    当你想到路由时,通常会想到类似 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;
                     800px;
                    height: 250px;
                    /* vertically centered text */
                    line-height: 250px;
                    border: 2px solid #555;
                    margin: 32px;
                    text-align: center;
                }
                .route {
                    cursor: pointer;
                    justify-content: center;
                     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 加载的某些内容。由于这只是“前端”示例,因此我无法向你展示太多内容。但这就是它在客户端上的工作方式。

    广州VI设计公司https://www.houdianzi.com

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

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

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

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

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

  • 相关阅读:
    淘宝客服务费和佣金的区别是什么
    java编程出现的错误对应的解决方法
    若遇到APP无法抓包怎么办,可以通过安装drony 进行转发抓包
    Android逆向—苏宁金融app的data参数分析
    GMSSL 支持SM2/SM3/SM4
    Frida安装和使用
    JS 解析 bytearray 成字符串
    Pytorch-tensor的创建,索引,切片
    深度学习实战之线性回归1
    CCF CSP 201803-2 碰撞的小球
  • 原文地址:https://www.cnblogs.com/qianxiaox/p/14017416.html
Copyright © 2020-2023  润新知