路由是什么
在网络原理中,路由指的是分组从源到目的地时,决定端到端路径的网络范围的进程,做成硬件叫路由器,在路由器中维护着一个路由表,并根据此路由表决定下一跳的地址。在 web 中,一样的原理,是指根据不同的 url 给其分配不同的控制器(处理程序)。
前端路由的出现
在最初的 web 开发中,我们并不太关注到路由,这和当时的开发方式有关,是后端模板的渲染方式,我们常看到的 jsp,php 都是这种方案,由后端根据请求信息来决定显示什么样的页面,此时路由是在服务端配置的。这时候的路由就是 url 和后端服务器的交互,根据不同的路径显示不同的资源,页面也是一种资源。这种开发方式有明显的不足,每切换一个页面都要重新加载一次,即使两个页面有很多相同的地方。还有就是前后端的代码揉杂在一起,前端要部署一个既有前端代码又有后端代码的项目,不方便本地开发调试,一旦后端代码有错误,前端无法进行开发,前端被限制在后端的开发方式中,效率很低,前端迫切的需要一种革新来改变这种开发方式。
随着前后端分离和 MVVM 概念的兴起及前端工程化的发展,出现了一种新的开发方式,SPA 单页应用,前端圈迅速崛起,有了爆发式的发展。单页应用的意思是只有一个页面,是无刷新的,看到的页面之间的跳转其实只是组件的切换,同时 URL 也要相应的变化,为了实现这种单页应用,出现了前端路由。
前端路由到底是什么
那么前端路由到底是什么?用一句话说就是 URL 和组件树的映射关系。因为单页应用前端整个工程实际上只有一个页面,不同的 url 只是在切换不同的组件,实际上就是监听 url 的变化然后按照他的规则来进行匹配。
前端路由的实现
前端路由的实现方式主要有两种:
- hash
- history
1、hash 即 window.loacation.hash,url 中以“#”为标识符,如:http://www.xxx/com/list.html#complete ,这个值可读可写,读取时,可以用来判断网页状态,写入时会在不重新载入网页的情况下给浏览器增加一条历史记录,有了这种特性就有了前端路由的雏形,因为改变#之后的内容相当于改变了 url,但是并没有重新向服务器发送请求。JavaScript 可以通过 window.onhashchange 来监听 url 变化,以实现不同组件的切换。
目前主要的路由库有 vue-router,react-router,他们的主要功能是存储路由的 hash 以及对应的函数,然后监听 hash 的变化执行对应的函数。以 vue-router 为例,看一下他的监听源码:
setupListeners () { //设置监听器
const router = this.router
const expectScroll = router.options.scrollBehavior
const supportsScroll = supportsPushState && expectScroll
if (supportsScroll) {
setupScroll()
}
window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
const current = this.current
if (!ensureSlash()) {
return
}
this.transitionTo(getHash(), route => {
if (supportsScroll) {
handleScroll(this.router, route, current, true)
}
if (!supportsPushState) { // hash变化改变view
replaceHash(route.fullPath)
}
})
})
}
这里他把 hashchange 是作为降级方案处理的,因为有更优的处理方式,下面会讲。这里只是设置监听的代码,当然他的前后还有一些“钩子”,即跳转前,跳转后要执行的方法,甚至有可能取消此次跳转。
2、由于 html5 的发布,引入了 history.pushState()
和 history.replaceState()
方法,它们分别可以添加和修改历史记录条目。pushState 需要三个参数,一个状态对象(可以通过 onpopstate 事件获取到),一个标题 (目前被忽略)和一个 URL,replaceState 参数也是一样。通常与 window.onpopstate
配合使用,这个为前端路由的另一种模式奠定了基础,但是这种方式的 url 是一个完整的如http://www.xxx.com/list/complete
,他每一次改变都会向服务发送一次请求资源(其实我们是没有这个页面地址的),所以需要服务器端增加一条配置,如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是我们的主页面。
下面我们用此种方法做一个简版的路由,开发思想涉及到了观察者模式,都是考虑最简单的情况。
imageimage
image
结尾
目前 web 路由整体思路上是一样的,将 url 映射到组件,在加上一系列的复杂情况的处理,比如说 hash 模式和 history 模式如何兼容,重定向,别名,嵌套,传参,然后是跳转,路由之间的跳转需要提供各种“钩子”,处理好各种情况就是一个完整的前端路由库了。
image
网友评论