当你想到路由时,通常会想到类似 react 之类的库。但实际上,这些库和框架仍然使用 vanilla JavaScript。那么该怎么实现呢?
我希望这个“JavaScript 路由教程”能够帮你了解如何用原生 JS 写出自己的路由。
我遇到了很多出于各种原因想要自己创建路由的人。既然你看到本文,那意味着你可能也是其中的一个!
最重要的是,使用 vanilla JS router 可以减少你对框架的依赖。
只要你了解实现它所涉及的所有部分,就可以相对容易的在原生 JavaScript 中创建自己的路由。
以下是制作自己的 JS router 时要了解的关键事项:
首先,我们将处理 History API。
我看过很多没有提到 JavaScript History API 的 vanilla JS router 教程。太糟糕了,因为单击浏览器的“后退”和“前进”按钮与浏览历史记录中的 URL 导航有关。如果没有 History API,就无法谈论路由。
我将简单地对的 html、css 和 JavaScript 进行注释。
先让我们仔细研究构建 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;
width: 800px;
height: 250px;
/* vertically centered text */
line-height: 250px;
border: 2px solid #555;
margin: 32px;
text-align: center;
}
.route {
cursor: pointer;
justify-content: center;
width: 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 传递给它即可:home,about,gallery 等。它们应与你要导航到的实际页面一致。当然这不是存储页面名称的唯一方法,例如可以用 array [] 或其他任何方式。这就是本例中的操作方式。
当然我们还需要从服务器加载有关该位置的布局和资源的内容。这取决于你的程序。可以是任何东西。
通过使用 history.pushState,你将自动使 Back 和 Forward 按钮导航到上一个或下一个状态。这样做会产生 popstate事件。这是你必须再次更新视图的部分。 (第一次是我们单击按钮时。)
但是由于该事件带有单击的 id,因此单击 Back 或 Forward 时很容易刷新视图并重新加载内容。
我们在这里没有使用 React 或 vue,因此在我的源代码中 load_content 将负责直接在 dom 中更新视图。此区域可能填充了你的 API 加载的某些内容。由于这只是“前端”示例,因此我无法向你展示太多内容。但这就是它在客户端上的工作方式。
将它们放在一起还需要再执行一个步骤。在我的例子中,只用了 router.html。当你第一次在 PWA 中加载此路由时,必须确保如果直接在地址栏中输入/page/home时,它可以工作。
到目前为止,我们仅从前端更改了路由器地址。假定每次你导航到出现在路由按钮上的 URL 时,实际上都会从服务器单独加载该 URL。
因此你有责任确保/page/about 将路由器和页面的加载到应用程序的根视图中。它还应突出显示“current”按钮。
实施完毕后,你的路由就完成了。你如何选择重新加载 #content 元素中的内容完全取决于你自己和你的后端设计。
在使用vue-cli搭建的环境中,浏览器上URL地址中是存在#的,这是由于vue-router 默认 hash 模式,不难发现#的出现真的很丑陋。官网给出了如何使用history模式mode: history
vue中路由传参主要的3种方式:query方式(push时使用path来匹配)、params模式(push时使用name来匹配)、location预声明参数模式(push使用path来匹配,但是它跟params模式不同)
我们的通用的后台管理系统中,我们会根据权限的粗细不同,会对每个角色每个权限每个资源进行控制。同样的我们也需要实现一个这样的功能。 这篇文章我将主要讲vue端的实现,关于后台接口我就不会涉及,当我接触的时候我们的后台接口是springcloud实现。
前后端分离开发模式,后端会把路由控制丢在前端,这几天再开发单页面小的项目,手动撸了个路由。前端路由实现有两种方法。HTML5 History API包括2个方法:history.pushState()和history.replaceState(),和1个事件:window.onpopstate。hash + location.onhashchange
在后台管理系统中,一般都会采用权限管理。路由菜单数据都会保存到数据库中,在vue-router 2.2版本新增了一个router.addRoutes(routes)方法,即可用它来实现动态路由了
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
原本想用动态路由的思路去做,按权限加载对应路由表,但是由于权限可以交叉(比如一个人可以同时是主题管理员和数据服务管理员),导致权限路由表还是得去做判断组合。于是放弃了这个思路,索性就在beforeEach里直接判断了。
使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,webpack在打包的时候会把整个路由打包成一个js文件,如果页面一多,会导致这个文件非常大,加载缓慢
query和params的区别,query相当于get请求,在页面跳转的时候,可以在地址栏看到请求参数,然而params则相当于post请求,参数不会在地址栏中显示。
当服务端接收到HTTP请求时,可以通过onRequest() 获取到url, pathname,query,及paramParams参数;为了解析这些数据需要使用url和querystring模块
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!