路由
什么是路由?
路由其实是网络工程中的一个术语
- 在架构一个网络时,非常重要的两个设备就是路由器和交换机。
- 当然,目前在我们生活中路由器也是越来越被大家所熟知,因为我们生活中都会用到路由器:
- 事实上,路由器主要维护的是一个映射表;
- 映射表会决定数据的流向;
路由的概念在软件工程中出现,最早是在后端路由中实现的,原因是web的发展主要经历了这样一些阶段: 后端路由阶段; 前后端分离阶段; 单页面富应用(SPA);
SPA
SPA,即单页面应用(Single Page Application)。SPA 是一种特殊的 Web 应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的。它将所有的活动局限于一个 Web 页面中,仅在该 Web 页面初始化时加载相应的 HTML 、 JavaScript 、 CSS 。一旦页面加载完成, SPA 不会因为用户的操作而进行页面的重新加载或跳转,而是利用 JavaScript 动态的变换 HTML(采用的是 div 切换显示和隐藏),从而实现UI与用户的交互。在 SPA 应用中,应用加载之后就不会再有整页刷新。相反,展示逻辑预先加载,并有赖于内容Region(区域)中的视图切换来展示内容
现如今,为了配合单页面 Web 应用快速发展的节奏,各类前端组件化技术栈层出不穷。近几年来,通过不断的版本迭代, vue 和 react 两大技术栈脱颖而出,成为当下最受欢迎的两大技术栈。
- 优点
-
有良好的交互体验
- 能提升页面切换的体验 用户在访问应用页面时不会频繁的去切换浏览页面,从而避免页面的重新加载
-
前后端分离开发
- 单页web应用可以和restful规约一起使用,通过restapi提供接口数据库,并使用ajax异步获取
-
共用一套后端程序代码
- 不用修改后端程序代码可以同时用于web界面,手机,平板等多个客户端
-
减轻服务器压力
- 服务器只用发数据就可以了,不用管展示的逻辑和页面的合成
-
- 缺点
- SEO难度高
- 所有内容都在一个页面中动态替换显示
- 前进,后退管理
- 由于单页Web应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理,当然此问题也有解决方案,比如利用URI中的散列+iframe实现;
- ** 初次加载耗时多**
- 为实现单页Web应用功能及显示效果,需要在加载页面的时候将JavaScript、CSS统一加载,部分页面可以在需要的时候加载。所以必须对JavaScript及CSS代码进行合并压缩处理;
- SEO难度高
URL的和hash
-
前端路由是如何做到URL和内容进行映射呢?监听URL的改变.
-
URL的hash
- URL的hash也就是锚点(#),本质上是改变
window.location的href属性 - 我们可以通过直接赋值
location.hash来改变href,但是页面不发生刷新; -
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="app"> <a href="#/home">home</a> <a href="#/about">about</a> <div class="router-view"></div> </div> <script> // 1.获取router-view const routerViewEl = document.querySelector(".router-view"); // 2.监听hashchange window.addEventListener("hashchange", function () { switch (location.hash) { case "#/home": routerViewEl.innerHTML = "home"; break; case "#/about": routerViewEl.innerHTML = "about"; break; default: routerViewEl.innerHTML = "default"; break; } }); </script> </body> </html>
- URL的hash也就是锚点(#),本质上是改变
HTML5的History
- hash的优势就是兼容性更好,在老版IE中都可以运行,但是缺陷是有一个#,显得不像一个真实的路径。
history接口是HTML5新增的,他有六种模式改变URL而不刷新页面
replaceState:替换原来的路径;
pushState:使用新的路径;
pushState()不会造成hashchange事件调用,即使新的 URL 和之前的 URL 只是锚的数据不同。ppopState:路径的回退;
go:向前或向后改变路径;
forward:向前改变路径;
back:向后改变路径;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<a href="#/home">home</a>
<a href="#/about">about</a>
<div class="router-view"></div>
</div>
<script>
// 1.获取router-view
const routerViewEl = document.querySelector(".router-view");
// 2.监听所有a元素
const aEls = document.getElementsByTagName("a");
for (const aEl of aEls) {
aEl.addEventListener("click", function (e) {
e.preventDefault();
const href = aEl.getAttribute("href");
console.log("[Log] href-->", href);
history.pushState({}, "", href);
});
}
// 3, 监听popstate和go操作
window.addEventListener("popstate", historyChange);
window.addEventListener("go", historyChange);
// 4.执行设置页面操作
function historyChange() {
console.log("[Log] location.hash-->", location.hash);
switch (location.hash) {
case "#/home":
routerViewEl.innerHTML = "home";
break;
case "#/about":
routerViewEl.innerHTML = "about";
break;
default:
routerViewEl.innerHTML = "default";
break;
}
}
</script>
</body>
</html>