如何使用窗口事件监听器在JavaScript中建立一个简单的路由器

253 阅读4分钟

如何使用窗口事件监听器在JavaScript中构建一个简单的路由器

路由器是一个JavaScript对象,它将URL映射到函数。路由器根据URL调用一个函数。

在过去,一个网络应用程序是一系列相互连接的页面。这可以是静态页面,也可以是在服务器上生成的动态页面。

单页网络应用程序是一个新概念,应用程序的寿命围绕着一个单一的HTML文档。

随后,网页被视图所取代。在大多数Web框架中,链接不再用于生成和导航页面,而是与视图绑定。

视图是一个JavaScript对象,包含单个网页的逻辑。视图处理页面的渲染和用户输入。所有的视图都是由路由器控制的。

这个概念

路由器观察URL的变化并调用适当的函数。然后,该方法负责渲染视图。

将路由器视为一个处理所有路由逻辑的大函数。路由器在应用程序中调用一些预定义的函数。

例如,如果URL是/about ,路由器将调用about 函数。被调用的方法将调用其他处理数据或DOM操作的函数。

视图可以是一个简单的函数,创建一个div 元素并将其附加到正文中。

为了演示这个概念,让我们在JavaScript中创建一个简单的路由器。

创建两个文件。

  1. index.html
  2. script.js

在你的index.html ,创建一个ID为:"app "的div 。同时,链接script.js 文件。

<div id="app"></div>
<script src="./script.js"></script>

这就是index.html 文件的全部内容。

在你的script.js 文件中,创建两个对象来保存路由和将被呈现的模板函数。

let routes = {};
let templates = {};

然后创建两个函数来显示homeabout 页面。虽然箭头函数可以用来定义这些方法,但为了简单起见,我们将使用普通函数。

let app_div = document.getElementById('app');

function home() {
    let div = document.createElement('div');
    let link = document.createElement('a');
    link.href = '#/about';
    link.innerText = 'About';

    div.innerHTML = '<h1>Home</h1>';
    div.appendChild(link);

    app_div.appendChild(div);
};

function about() {
    let div = document.createElement('div');
    let link = document.createElement('a');
    link.href = '#/';
    link.innerText = 'Home';

    div.innerHTML = '<h1>About</h1>';
    div.appendChild(link);

    app_div.appendChild(div);
};

然后我们定义路由。一个路由是由一个路径和一个要渲染的模板定义的。模板可以是一个创建DOM元素的函数或一个文件名(字符串)。

function route (path, template) {
    if (typeof template === 'function') {
        return routes[path] = template;
    }
    else if (typeof template === 'string') {
        return routes[path] = templates[template];
    } else {
        return;
    };
};

路由函数需要两个参数。1.path :要映射到模板的路径。2.template :要渲染的模板。

我们检查该模板是一个函数还是一个字符串。如果它是一个函数,我们将它存储在routes 对象中。如果是字符串,我们将模板函数存储在templates 对象中。

下一步是注册一个将充当模板引擎的函数。

function template (name, templateFunction) {
    return templates[name] = templateFunction;
};

模板函数需要两个参数。

  1. name: 模板的名称。
  2. templateFunction:将创建DOM元素的函数。

现在你可以将一个模板映射到一个路由,如下图所示。

template('home', function(){
    home();
});

template('about', function(){
    about();
});

我们将home 模板映射到/home 路由,将/about 模板映射到about 路由。

然后定义路由到模板的映射。

route('/', 'home');
route('/about', 'about');

我们将模板名称与将创建和追加DOM元素到应用程序的函数相匹配div

我们需要做的是检测和解决URL中的变化,以呈现正确的模板,如下所示。

function resolveRoute(route) {
    try {
        return routes[route];
    } catch (e) {
        throw new Error(`Route ${route} not found`);
    };
};

resolveRoute 方法返回基于路由的模板函数。如果没有找到路由,它会抛出一个错误。

我们需要创建一个router ,该函数将从URL哈希中获取路由并调用模板函数。这一点在下面强调。

function router(evt) {
    let url = window.location.hash.slice(1) || '/';
    let route = resolveRoute(url);

    route();
};

为了在视图之间切换,你需要监听loadhashchange 事件。当页面被加载时,加载事件被触发。

另一方面,当URL hash 变化时,hashchange 事件被触发。

window.addEventListener('load', router);
window.addEventListener('hashchange', router);

在这一点上,简单的路由器已经准备好了。

当你在浏览器中打开index.html 文件时,你应该看到主页。

点击about 链接应该可以导航到关于页面。

总结

在本教程中,你用JavaScript创建了一个简单的路由器。然而,作为一个简单的路由器,它只能处理基本的路由映射。

它缺乏许多更复杂的路由器所具有的功能。例如,它不支持嵌套路由。

为了增加这些功能,你必须编写更多的函数来处理路由逻辑。

另外,你可以使用[React Router]这样的库。npm上也有更多的路由库可用。

如果你喜欢用香草的JavaScript工作,你可以从[Navigo]开始。