如何使用窗口事件监听器在JavaScript中构建一个简单的路由器
路由器是一个JavaScript对象,它将URL映射到函数。路由器根据URL调用一个函数。
在过去,一个网络应用程序是一系列相互连接的页面。这可以是静态页面,也可以是在服务器上生成的动态页面。
单页网络应用程序是一个新概念,应用程序的寿命围绕着一个单一的HTML文档。
随后,网页被视图所取代。在大多数Web框架中,链接不再用于生成和导航页面,而是与视图绑定。
视图是一个JavaScript对象,包含单个网页的逻辑。视图处理页面的渲染和用户输入。所有的视图都是由路由器控制的。
这个概念
路由器观察URL的变化并调用适当的函数。然后,该方法负责渲染视图。
将路由器视为一个处理所有路由逻辑的大函数。路由器在应用程序中调用一些预定义的函数。
例如,如果URL是/about ,路由器将调用about 函数。被调用的方法将调用其他处理数据或DOM操作的函数。
视图可以是一个简单的函数,创建一个div 元素并将其附加到正文中。
为了演示这个概念,让我们在JavaScript中创建一个简单的路由器。
创建两个文件。
index.htmlscript.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 = {};
然后创建两个函数来显示home 和about 页面。虽然箭头函数可以用来定义这些方法,但为了简单起见,我们将使用普通函数。
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;
};
模板函数需要两个参数。
name: 模板的名称。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();
};
为了在视图之间切换,你需要监听load 和hashchange 事件。当页面被加载时,加载事件被触发。
另一方面,当URL hash 变化时,hashchange 事件被触发。
window.addEventListener('load', router);
window.addEventListener('hashchange', router);
在这一点上,简单的路由器已经准备好了。
当你在浏览器中打开index.html 文件时,你应该看到主页。
点击about 链接应该可以导航到关于页面。
总结
在本教程中,你用JavaScript创建了一个简单的路由器。然而,作为一个简单的路由器,它只能处理基本的路由映射。
它缺乏许多更复杂的路由器所具有的功能。例如,它不支持嵌套路由。
为了增加这些功能,你必须编写更多的函数来处理路由逻辑。
另外,你可以使用[React Router]这样的库。npm上也有更多的路由库可用。
如果你喜欢用香草的JavaScript工作,你可以从[Navigo]开始。