何为前端路由?
路由(Router)这个概念最先是后端出现的,是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能。
前端随着 ajax 的流行,数据请求可以在不刷新浏览器的情况下进行。异步交互体验中最盛行的就是 SPA —— 单页应用。单页应用不仅仅是在页面交互时无刷新的,连页面跳转都是无刷新的,为了实现单页应用,所以就有了前端路由。
前端Router基本功能
一个基本的前端路由至少应该提供以下功能:
-
前端Router可以控制浏览器的 history,使的浏览器不会在 URL 发生改变时刷新整个页面。
-
前端Router需要维护一个 URL 历史栈,通过这个栈可以返回之前页面,进入下一个页面。
前端路由实现原理就是匹配不同的 url 路径,进行解析,然后动态的渲染出区域 html 内容。但是这样存在一个问题,就是 url 每次变化的时候,都会造成页面的刷新。那解决问题的思路便是在改变 url 的情况下,保证页面的不刷新。目前 Router有两种实现方式 History 和 hash。
Hash 路由
URL Hash 的形式类似如下:
// 表示文章列表页面 https://www.limitcode.com/#/list // 表示文章详情页面 https://www.limitcode.com/#/detail
# 后面的内容即我们说的 hash 值。hash 用于表示页面的一个位置,当浏览器加载完页面后,会滚动到 hash 所指向的位置,这是 URL hash 最初的目的。
由于 hash 在浏览器中的特性,开发者们发现 hash 非常适合用来实现前端 Router。hash 具有实现前端Router的以下特点,我们一起来看看。
-
hash 只作用在浏览器,不会在请求中发送给服务器。
-
hash 发生变化时,浏览器并不会重新给后端发送请求加载页面。
-
修改 hash 时会在浏览器留下历史记录,可以通过浏览器返回按钮回到上一个页面。
-
hash 发生变化时会触发 hashchange 事件,在该事件中可以通过 window.location.hash 获取到当前 hash值。
// router.js function Router() { this.routes = [] /* 添加路由 */ this.add = function (re, handler) { this.routes.push({re, handler}) } /* 监听 url 变化 */ this.listen = function () { //路由切换 window.addEventListener('hashchange', function(event) { var hash = window.location.hash for (var i = 0; i ++; i < this.routes.length) { if (hash === this.routes[i].re) { this.routes[i].handler.apply({}) } } }, false) } /* 前进到一个新的url */ this.push = function (path) { window.location.hash = path || '' } /* 替换成一个新的url */ this.replace = function (path) { path = path || '' var i = window.location.href.indexOf('#') window.location.replace(window.location.href.slice(0, i >= 0 ? i : 0) + "#" + path) } /* 返回到上一个url */ this.back = function () { window.history.back() } }
// router.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="router.js"></script> </head> <body> <div> <button id="btn">点击跳转到 list</button> </div> <script> var router = new Router(); router.add('/list', function () { }) router.add('/detail', function () { }) router.listen(); var btn = document.getElementById('btn'); btn.addEventListener('click', function (e) { router.push('/list') }) </script> </body> </html>
History 路由
History 在H5出现之前,可以使用 History.back() 向后跳转,使用 History.forward() 控制向前跳转。
在 H5 中新增了 history.pushState() 和 history.replaceState(),分别可以添加和修改历史记录。
window.history.pushState({}, "title", "https://www.limitcode.com/list"); window.history.replaceState({}, "title", "https://www.limitcode.com/detail");
和 hash 一样,使用 pushState 和 replaceState 修改 URL 同样有 hash 具备的特点。浏览器历史记录的变更会触发 window 的 onpopstate 事件,可以根据这个事件来监听 URL的变化。
// router2.js function Router() { this.routes = [] /* 添加路由 */ this.add = function (re, handler) { this.routes.push({re, handler}) } /* 监听 url 变化 */ this.listen = function () { //路由切换 window.addEventListener('popstate', function(event) { var pathname = window.location.pathname for (var i = 0; i ++; i < this.routes.length) { if (pathname === this.routes[i].re) { this.routes[i].handler.apply({}) } } }) } /* 前进到一个新的url */ this.push = function (path) { window.history.pushState({}, '', path) } /* 替换成一个新的url */ this.replace = function (path) { window.history.replaceState({}, '', path) } /* 返回到上一个url */ this.back = function () { window.history.back() } }
// router2.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="router2.js"></script> </head> <body> <div> <button id="btn">点击跳转到 list</button> </div> <script> var router = new Router(); router.add('/list', function () { }) router.add('/detail', function () { }) router.listen(); var btn = document.getElementById('btn'); btn.addEventListener('click', function (e) { router.push('/list') }) </script> </body> </html>
History 和 Hash 对比
-
hash 使用 # 后面的内容模拟一个完整路径,不太美观。
-
hash 在请求时不会发送给服务器,用户手动刷新页面,后端接受到了也是同一个地址。
-
History 直接修改浏览器 URL,用户手动刷新页面,后端接受到是不同的地址,需要后端做处理跳转到统一的html页面。
本文转载自:https://www.limitcode.com/detail/5e5e603810dcbf0b1852b3c0.html