构建一个非常基本的 SPA JavaScript 路由器简单纯 JavaScript 路由器关键要点:文档:我决定使用 RouteNow

2025-06-07

构建一个非常基本的 SPA JavaScript 路由器

简单纯 JavaScript 路由器

关键要点:

文档:

我决定

路线现在

简单纯 JavaScript 路由器

在本文中,我将使用纯 JavaScript 实现一个极其基础的 SPA 路由。
目标是演示如何使用 JavaScript 根据 URL 渲染不同的动态内容。

要求

我们想要一个基本的网站,根据 3 个 URL 显示不同的主题:

对于其他 URL,我们会显示错误消息。
我们可以使用 HTML 和纯 JavaScript。

设置

让我们创建 HTML 页面index.html

<html>
  <head>
    <title>JavaScript Router Example</title>
  </head>
  <body>
    <header>
      <h1>JavaScript Router Example</h1>
    </header>
    <section id="app"></section>
    <nav>
      <a href="/">Home</a> -
      <a href="#/page1">Page 1</a> -
      <a href="#/page2">Page 2</a>
    </nav>
    <script type="text/javascript" src="./app.js" />
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

和一个空的 JS 文件app.js

为了提供服务,我们可以live-server全局安装:

npm install -g live-server
Enter fullscreen mode Exit fullscreen mode

然后在我们的 HTML 文件上运行它:

live-server --port=3000 --entry-file=’./index.html’
Enter fullscreen mode Exit fullscreen mode

现在应该可以访问http://localhost:3000/并查看该页面了。

创建组件

现在让我们创建组件。

我们使用“模板文字”表达式,它是一个可以跨越多行并插入表达式的字符串文字。

每个组件都有一个render返回 HTML 模板的方法。

// Components
const HomeComponent = {
  render: () => {
    return `
      <section>
        <h1>Home</h1>
        <p>This is just a test</p>
      </section>
    `;
  }
} 

const Page1Component = {
  render: () => {
    return `
      <section>
        <h1>Page 1</h1>
        <p>This is just a test</p>
      </section>
    `;
  }
} 

const Page2Component = {
  render: () => {
    return `
      <section>
        <h1>Page 2</h1>
        <p>This is just a test</p>
      </section>
    `;
  }
} 

const ErrorComponent = {
  render: () => {
    return `
      <section>
        <h1>Error</h1>
        <p>This is just a test</p>
      </section>
    `;
  }
}
Enter fullscreen mode Exit fullscreen mode

现在我们有了想要在页面中显示的组件。

创建路线

我们需要创建路线并以某种方式将它们与组件连接起来。

那么,让我们用一种简单的方法来做这件事:

// Routes 
const routes = [
  { path: '/', component: HomeComponent, },
  { path: '/page1', component: Page1Component, },
  { path: '/page2', component: Page2Component, },
];
Enter fullscreen mode Exit fullscreen mode

路由器

路由器应该是什么样子的?
假设我们的目标是编写如下代码:

const router = () => {
  // TODO: Get the current path
  // TODO: Find the component based on the current path
  // TODO: If there's no matching route, get the "Error" component
  // TODO: Render the component in the "app" placeholder
};
Enter fullscreen mode Exit fullscreen mode

那我们就开始吧!:)

获取当前路径

location物体正是我们需要的工具。

Location 接口表示其所链接对象的位置(URL)。对其所做的更改会反映在其关联的对象上。Document 和 Window 接口都具有这样的链接 Location,可分别通过 Document.location 和 Window.location 访问。(MDN Web 文档

位置对象的一个​​属性是location.hash,它包含从“#”开始的 URL 部分,后跟 URL 的片段标识符。

换句话说,给定此 URL:http://foo.bar/#/hello,location.hash 将是:'#/hello'。

因此我们需要从该字符串中提取一些可以使用的内容routes

我们从中删除“#”字符,如果提供了任何哈希值,我们假设它将是基本 url /:。

const parseLocation = () => location.hash.slice(1).toLowerCase() || '/';
Enter fullscreen mode Exit fullscreen mode

此时我们解决了列表中的第一个“TODO”:

const router = () => {
  //  Find the component based on the current path
  const path = parseLocation();
  // TODO: If there's no matching route, get the "Error" component
  // TODO: Render the component in the "app" placeholder
};
Enter fullscreen mode Exit fullscreen mode

获取正确的组件

因为我们有path,所以我们需要做的就是获取第一个匹配的条目routes

如果我们找不到任何路线,我们就返回undefined

const findComponentByPath = (path, routes) => routes.find(r => r.path.match(new RegExp(`^\\${path}$`, 'gm'))) || undefined;
Enter fullscreen mode Exit fullscreen mode

我们现在解决下一个 TODO!
我们使用“解构赋值”将匹配的组件赋值给 const component,默认情况下, const 会返回ErrorComponent
由于“解构赋值”要求右侧有一个对象,而我们的findComponentByPath函数可以返回undefined,因此在本例中我们只提供一个空对象{}

const router = () => {
  // Find the component based on the current path
  const path = parseLocation();
  // If there's no matching route, get the "Error" component
  const { component = ErrorComponent } = findComponentByPath(path, routes) || {};
  // TODO: Render the component in the "app" placeholder
};
Enter fullscreen mode Exit fullscreen mode

现在我们准备解决第三个也是最后一个 TODO:在应用程序中渲染组件。

渲染组件

如果你还记得的话,我们的组件有一个render返回 HTML 模板的方法。
所以我们必须把这个模板放到 app 中<section id="app"></section>

这很简单,你知道的。
我们通过 id 获取元素,然后把内容放到innerHTML属性里。

document.getElementById('app').innerHTML = component.render();
Enter fullscreen mode Exit fullscreen mode

router准备好:

const router = () => {
  // Find the component based on the current path
  const path = parseLocation();
  // If there's no matching route, get the "Error" component
  const { component = ErrorComponent } = findComponentByPath(path, routes) || {};
  // Render the component in the "app" placeholder
  document.getElementById('app').innerHTML = component.render();
};
Enter fullscreen mode Exit fullscreen mode

让它发挥作用

即使代码能运行,也还是缺少了一些东西。
我们根本没调用router!我们的代码还没执行呢。

我们需要在两种情况下调用它:
1)在页面加载时,因为我们希望从一开始就显示正确的内容
2)在每次位置更新时(实际上是每次“哈希”位置更新)

我们需要添加事件监听器并将它们与我们的绑定router

window.addEventListener('hashchange', router);
window.addEventListener('load', router);
Enter fullscreen mode Exit fullscreen mode

就是这样 :)

您可以在这里找到一个实例:

关键要点:

• 了解 Window.location 的工作原理
• 了解模板文字的工作原理
• 了解 EventTarget.addEventListener() 的工作原理

文档:

Window.location
模板文字(模板字符串)
EventTarget.addEventListener()

关于这篇文章

我在pixari.slack.com上运营一个免费的 JavaScript 学习小组,并将此博客用作社区的官方博客。 我会从 #questions-answer 频道挑选一些问题,并通过博客文章进行解答。这样,我的答案将永久可见,供所有人查看。

如果您想加入社区,请随时单击此处或联系我:

文章来源:https://dev.to/pixari/build-a-very-basic-spa-javascript-router-2k4p
PREV
帮助您选择正确 HTML 标签的简短指南
NEXT
只需 5 分钟即可创建您的第一个超棒 Chrome 扩展程序!🔥🔥🔥(内含常见问题解答 🤔 => 😊)常见问题解答