使用 History API 构建 JavaScript 路由器

本文介绍了如何在纯JavaScript环境下构建客户端路由系统,通过创建一个简单的服务器提供HTML文件,并利用window.onload事件处理函数实现路由逻辑。主要内容包括设置HTML样板,创建路由器实例,根据当前URL显示相应内容,添加路由器链接以及实现页面导航功能,最后将路由逻辑提取到单独的routes.js文件中。这种方法适用于单页应用,便于理解和维护。
摘要由CSDN通过智能技术生成

在本文中,我们将构建一个客户端路由系统。客户端路由是一种路由类型,用户在其中导航应用程序,即使页面的 URL 发生更改,也不会重新加载整个页面,而是显示新内容。

为了构建它,我们需要一个简单的服务器来提供我们的index.html文件。准备好?让我们开始。

让我们为我们的 HTML 创建一个简单的样板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Javascript Routing</h1>
    <div id="app">
    </div>

    <script src="main.js"></script>
</body>
</html>

在这里,我们将链接main.js文件,以便我们可以在任何时间点操作 DOM。

实现路由系统

让我们转到main.js文件并编写我们所有的路由器逻辑。我们所有的代码都将被包装在window.onload其中,以便它们仅在网页完全加载其所有内容后才执行脚本。

接下来,我们将创建一个路由器实例,它是一个带有两个参数的函数。第一个参数将是路线的名称,第二个参数将是一个包含我们定义的所有路线的数组。这条路线将有两个属性:路线的名称和路线的路径。

window.onload = () => {
// get root div for rendering
    let root = document.getElementById('app');

  //router instance
    let Router = function (name, routes) {
        return {
            name,
            routes
        }
    };

 //create the route instance
    let routerInstance = new Router('routerInstance', [{
            path: "/",
            name: "Root"
        },
        {
            path: '/about',
            name: "About"
        },
        {
            path: '/contact',
            name: "Contact"
        }
    ])

}

我们可以获取我们页面当前的路由路径,并根据该路由显示一个模板。location.pathname返回页面的当前路由,我们可以将这段代码用于我们的 DOM:

let currentPath = window.location.pathname;
    if (currentPath === '/') {
        root.innerHTML = 'You are on Home page'
    } else {
        // check if route exist in the router instance 
        let route = routerInstance.routes.filter(r => r.path === currentPath)[0];
        if (route) {
            root.innerHTML = `You are on the ${route.name} path`
        } else {
            root.innerHTML = `This route is not defined`
        }
    }

我们将使用该currentPath变量来检查路由实例中是否定义了路由。如果路由存在,我们将呈现一个简单的 HTML 模板。如果没有,我们将This route is not defined显示在页面上。

随意显示您选择的任何形式的错误。例如,如果路由不存在,您可以将其重定向回主页。

添加路由器链接

对于页面导航,我们可以添加路由器链接。就像使用Angular一样,您可以传递一个routerLink具有您要导航到的路径的值的值。为了实现这一点,让我们在index.html文件中添加一些链接:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <nav>
        <button router-link="/">Home</button>
        <button router-link="/about">About</button>
        <button router-link="/contact">Contact</button>
        <button router-link="/unknown">Error</button>
    </nav>
    <h1>Javascript Routing</h1>
    <div id="app">
    </div>

    <script src="main.js"></script>
</body>
</html>

注意我们传入的router-link属性——这是我们将用于路由的属性。

我们将创建一个存储所有的router-link变量并将其存储在一个数组中:

let definedRoutes = Array.from(document.querySelectorAll('[router-link]'));

在将我们的路由链接存储在一个数组中之后,我们可以遍历它们并添加一个调用navigate()函数的点击事件侦听器:

//iterate over all defined routes
    definedRoutes.forEach(route => {
        route.addEventListener('click', navigate, false)
    })

定义导航功能

导航功能将使用Javascript History API进行导航。history.pushState()方法将状态添加到浏览器的会话历史堆栈。

单击按钮时,我们将收到该按钮的路由器链接属性,然后使用history.pushState()导航到该路径,然后更改呈现的 HTML 模板:

  // method to navigate
    let navigate = e => {
        let route = e.target.attributes[0].value;

        // redirect to the router instance
        let routeInfo = routerInstance.routes.filter(r => r.path === route)[0]
        if (!routeInfo) {
            window.history.pushState({}, '', 'error')
            root.innerHTML = `This route is not Defined`
        } else {
            window.history.pushState({}, '', routeInfo.path)
            root.innerHTML = `You are on the ${routeInfo.name} path`
        }
    }

如果一个 nav 链接有一个未在 中定义的路由器链接routeInstance,它会将推送状态设置为This route is not Defined并在模板上error渲染。

接下来,您应该考虑将路由存储在单独的文件中,这样可以使代码更整洁,并且在出现任何错误时更易于调试。现在,创建routes.js文件并将路由构造函数和路由器实例提取到这个新文件中:

//router instance
let Router = function (name, routes) {
    return {
        name,
        routes
    }
};
let routerInstance = new Router('routerInstance', [{
        path: "/",
        name: "Root"
    },
    {
        path: '/about',
        name: "About"
    },
    {
        path: '/contact',
        name: "Contact"
    }
])

export default routerInstance

导出此文件使其可供其他 JavaScript 文件访问。我们可以将它导入到我们的 main.js 文件中:

import routerInstance from './routes.js'

这将引发错误。要修复它,请将 index.html 文件中的脚本标记修改为:

<script type="module" src="main.js"></script>

添加模块的类型指定可以在模块外部访问哪些变量和函数。

结论

了解如何在 Vanilla JavaScript 中实现路由系统可以让开发人员更轻松地使用框架路由库,例如Vue.js 路由器。我们这里的代码可以在单页应用程序中重用,当您在没有框架的情况下工作时这是完美的。要获取源代码,请查看GitHub

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值