路由的一些概念
路由
路由(routing)就是通过互联的网络把信息从源地址
传输到目的地址
的活动。
分发
路由通常根据路由表来引导分组转送。
路由表
一个存储到各个目的地的最佳路径的表。作成硬件的话,则称为路由器。
在前端的js中,我们一般将hash值和相应的标签绑定在一起
const routeTable = {
"1": div1, //左边是hash值,右边是div
"2": div2,
"3": div3,
"4": div4
};//将各个div集合到路由表,使用时直接使用路由表
默认路由和404
默认路由:没有选择的情况下,进入的默认路径
404:找不到相关路径,直接404
hash模式
思路:利用 URL 中的hash("#")来制定路径
缺点:SEO不友好,原因在于服务器收不到hash,浏览器不会将#号后面的数字发给服务器。
index.html
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<a href="#1">go to 1</a>
<a href="#2">go to 2</a>
<a href="#3">go to 3</a>
<a href="#4">go to 4</a>
<div id="app"></div>
<div id="div404" style="display: none;">你要找的内容被狗吃了</div>
<script src="src/index.js"></script>
</body>
</html>
index.js
const app = document.querySelector("#app");
const div1 = document.createElement("div");
div1.innerHTML = "1";
const div2 = document.createElement("div");
div2.innerHTML = "2";
const div3 = document.createElement("div");
div3.innerHTML = "3";
const div4 = document.createElement("div");
div4.innerHTML = "4";
const routeTable = {
"1": div1, //左边是hash值,右边是div
"2": div2,
"3": div3,
"4": div4
};//将各个div集合到路由表,使用时直接使用路由表
function route(container) {
let number = window.location.hash.substr(1);
number = number || 1;//默认路径设置为1
// 获取界面
let div = routeTable[number.toString()];
if (!div) {
div = document.querySelector("#div404");
} //设置404
// 展示界面
container.innerHTML = "";
container.appendChild(div);
}
route(app);
window.addEventListener("hashchange", () => {
console.log("hash 变了");
route(app);
});
history模式
思路:后端将所有前端路由都渲染到同一页面
缺点:IE8一下不支持
举例:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<a class="link" href="/1">go to 1</a> <a class="link" href="/2">go to 2</a>
<a class="link" href="/3">go to 3</a> <a class="link" href="/4">go to 4</a>
<div id="app"></div>
<div id="div404" style="display: none;">你要找的内容被狗吃了</div>
<script src="src/index.js"></script>
</body>
</html>
index.js
const app = document.querySelector("#app");
const div1 = document.createElement("div");
div1.innerHTML = "1";
const div2 = document.createElement("div");
div2.innerHTML = "2";
const div3 = document.createElement("div");
div3.innerHTML = "3";
const div4 = document.createElement("div");
div4.innerHTML = "4";
const routeTable = {
"/1": div1,
"/2": div2,
"/3": div3,
"/4": div4
};
function route(container) {
let number = window.location.pathname;
console.log("number: " + number);
if (number === "/") {
number = "/1";
}
// 获取界面
let div = routeTable[number.toString()];
if (!div) {
div = document.querySelector("#div404");
}
div.style.display = "block";
// 展示界面
container.innerHTML = "";
container.appendChild(div);
}
const allA = document.querySelectorAll("a.link");
for (let a of allA) {
a.addEventListener("click", e => {
e.preventDefault();
const href = a.getAttribute("href");
window.history.pushState(null, `page ${href}`, href);
// 通知
onStateChange(href);
});
}
route(app);
function onStateChange() {
console.log("state 变了");
route(app);
}
以上代码有hash 改编。
首先我们将html和js文件中所有的 #1..
改成 /1..
。
接着对 route()
这个展示页面的函数路径的函数进行修改:
let number = window.location.pathname;
把 window.location.hash.substr(1)
改成 window.location.pathname
这两步使得我们点击 标签以后,不再是:
http:... /#1
而是变成:
http:... /1
也就是说,我们的number
变成了从路径名获取
接下来的需求是利用 history 的相关属性,对 标签的点击事件进行修改:
const allA = document.querySelectorAll("a.link");
for (let a of allA) {
a.addEventListener("click", e => {
e.preventDefault();//阻止<a>标签的默认事件
const href = a.getAttribute("href");
window.history.pushState(null, `page ${href}`, href);
onStateChange(href); // 通知变更
});
}
首先我们用 e.preventDefault();
阻止 标签的默认跳转。
接着把 hashchange
事件改成window.history.pushState()
其相当于用 history API
给地址添加了一个路径字符串
memory 模式
memory 模式就是把 “路径” 存到 localstorage
里(用户看不见的地方)。当用户使用的时候从 localstorage 里取出来
前面两种模式都是将路径存在 url 上面。memory模式则是存在 localstorage
。
这种模式仅仅对单击有效,俗称单机版的路由。