前言
什么是路由?路由最开始的概念就是服务端用来描述路径的,也就是说在前端的领域里面最开始是没有"路由"这一概念的,但是随着技术的发展,人们对网页的浏览体验要求越来越高,于是乎,前段就也有了路由怎么个玩意,当用户点击链接时不再需要刷新页面然后看着那雪白的画面发呆一秒,而是直接切换对应的展示的代码,这一特点深受广大程序猿和用户的喜爱,因此前端路由也就名正言顺火了起来,但是,你真的知道这一特点是如何实现的吗?
正文
通过Hash值修改路径
举个很简单的例子,当你打开百度官网,然后在后面接上/123456
之后按下回车,这个时候虽然会显示404,但实际上你仔细观察会发现页面是进行了一次刷新的,即使刷新的再怎么快,那也是刷新了的。但如果在后面接的是#/123456
呢?这个时候你就会发现,虽然页面不变,但是至少浏览器不会刷新页面了。原因也很简单,浏览器会把路径后#后面的所有东西
都视作哈希值,而哈希值的改变不会引起页面的刷新。这样一来路径改了,页面也不刷新了,那如何修改页面呢?这个其实也很简,我们只需要对浏览器的地址进行监听,当地址修改后展示对应的HTML代码即可。话不多说直接上代码
首先,我们定义了一个<div>
元素,它的id
属性为"routerview"
,用于渲染不同页面的内容。
html
<div id="routerview"></div>
接着,我们定义了一个名为routers
的数组,其中包含了两个路由对象。每个路由对象都有一个path
属性和一个component
属性。path
属性表示路由的路径,这里是以哈希符号#
开头的字符串,例如"#/home"
和"#/about"
。component
属性表示该路径对应的组件或视图。在这个简单的示例中,我们只是使用了一个字符串来表示组件内容。
javascript
const routers = [
{
path: '#/home',
component: '这是首页'
},
{
path: '#/about',
component: '这是关于'
}
]
然后,我们需要监听URL的变化,通常情况下能够改变URL的方式有三种分别是a标签
,浏览器的前进和后退
以及通过修改window.location
。这三种方式无一例外都会触发一个事件------hashchange,所以我们只需要使用addEventListener
方法来监听浏览器的DOMContentLoaded
事件(用于应对浏览器dom元素的初次加载)和hashchange
事件,以便在这些事件发生时更新页面内容。当这些事件触发时,会调用onHashChange
函数。
javascript
window.addEventListener('DOMContentLoaded', onHashChange)
window.addEventListener('hashchange', onHashChange)
在onHashChange
函数中,我们首先使用location.hash
获取当前页面的哈希值,然后遍历routers
数组,根据当前哈希值来匹配对应的路由对象。如果找到了匹配的路由对象,就使用该路由对象的component
属性来更新routerview
元素的内容。
javascript
function onHashChange() {
console.log(location.hash);
routers.forEach((item, index) => {
if (item.path === location.hash) {
routerview.innerHTML = item.component
}
})
}
这样,当用户在浏览器地址栏中输入不同的哈希值或点击页面内的链接时,页面的routerview
元素会根据不同的路径显示相应的组件内容,实现了基本的前端路由功能。
总结起来,这段代码实现了基本的前端路由功能,使用了哈希路由来实现页面间的切换,并演示了如何使用location
对象和addEventListener
方法来监听URL的变化并动态更新页面内容。
这个方法几乎已经完美了,前提是你和你的用户不介意那个#。但这怎么可能呢,对于恨不得把前端整出花来的前端工程师来说,这个#简直就是眼中钉肉中刺,一天不去掉就一天睡不着觉,所以,接下来介绍的是另一种稍微复杂那么一点点的方法
History
既然都说了History的路径不会带有#,那么也就意味着修改URL时的值不再是哈希值,既然这样,组织页面的刷新就是就是我们最先要干的事。方法十分简单
js
const links = document.querySelectorAll('li a')
links.forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault()
//preventDefault函数阻止了a标签自带的跳转页面行为
// 添加一种可以修改URL但又不刷新页面的行为
})
这里我们是通过preventDefault方法去阻止HTML标签中自带的行为,比如常见的不让你复制内容的网页也是通过这个方法去阻止用户复制网页内容。那么到这里,页面跳转被阻止了,页面的刷新也就顺理成章没得用了。接下来的事情就和上面差不多了,也是先改变url,然后再修改对应的HTML代码
pushState
这里就不得不提到今天的主角之一了:history API,它提的了 pushState
方法,可以修改URL且不引起页面刷新。
js
history.pushState(null, '跳转后', a.getAttribute('href'))
这个方法需要三个参数分别是state
,title
和URL
,其中title这个参数基本不用了,但是由于种种历史原因(官方文档是这么说的)这个参数还不能被省略。这样一来,url也修改完成。剩下的就是包装一个函数用来监听url了,函数和上面差不多,这里就不过多赘述了。最后的问题来了,我们什么时候用这个函数?dom元素首次加载肯定是要的,这个不必多说,但是当我通过点击浏览器的前进或者后退呢?
popstate
这就是今天这篇文章最后的主角了,浏览器的前进或后退都会触发popstate事件,所以我们只需要添加一个时间监听popstate就可以知道用户是否在浏览器上进行了前进或者后退操作
js
window.addEventListener('popstate', onPopstate);
总结
利用 history API 可以方便地实现前端路由功能,从而提升单页面应用的用户体验和性能。通过定义路由表,监听 popstate 事件,以及在事件处理函数中根据 URL 的路径部分来渲染相应的视图组件,我们可以轻松地构建出一个可靠和高效的前端路由系统。然而这只是前端路由中最基础的修改页面渲染的功能,后续还有更多其他功能我也会出相关的文章介绍