前言

这个坑,已经埋在笔者的待办事项里很久,就好比一滴酱油滴在白色的桌子上,现在有时间了,很想把它“擦掉”

正文

前端路由实现有两种,一是 hash,另一种是 histroy。

hash 原本是为了定位,笔者印象中最开始是 PC 端商城的楼层,点击跳转到某一模块

history 是 HTML5 新出的 API,它属于 bom。通过 history 对象可以操作浏览器的会话历史以及向前向后跳转

笔者是 React 开发者,Vue 好久没用了,所以以下内容是以 React 的角度描写

前端开发——React 全家桶——路由采用第三方库 react-router 和—— react-router 的底层是 history

我们在写 react 的路由写法时,通常为两种,hash 和 history ,使用它的本质是 history 库

笔者在这里写个简单的

hash 模式

它的本质是通过监听hash变化事件来修改路由内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<body>
<a href="#/home">Home</a>
<a href="#/user">User</a>
<a href="#/about">About</a>
<div id="view"></div>
</body>
<script>
function onHashChange() {
const view = document.getElementById("view");
switch (location.hash) {
case "#/home":
view.innerHTML = "Home";
break;
case "#/user":
view.innerHTML = "User";
break;
case "#/about":
view.innerHTML = "About";
break;
default:
view.innerHTML = "Home";
break;
}
}
window.addEventListener("hashchange", onHashChange);
</script>

hash模式

history 模式

看了 hash 模式,我们会觉得很简单,无非是监听 hash 的变化,现在我们再看 history 模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<body>
<a href="/home">Home</a>
<a href="/user">User</a>
<a href="/about">About</a>
<div id="view"></div>
</body>
<script>
const elements = document.querySelectorAll("a[href]");
elements.forEach(el =>
el.addEventListener("click", e => {
e.preventDefault();
const test = el.getAttribute("href");
history.pushState(null, null, el.getAttribute("href"));
onPopState();
})
);

function onPopState() {
const view = document.getElementById("view");
switch (location.pathname) {
case "/home":
view.innerHTML = "Home";
break;
case "/user":
view.innerHTML = "User";
break;
case "/about":
view.innerHTML = "About";
break;
default:
view.innerHTML = "Home";
break;
}
}
window.addEventListener("popstate", onPopState);
</script>

无非是把 hashchange 改成了 popstate,当 history 对象变化时,会出发 onPopState 事件,而我们的 history 模式不想 hash 模式那样,点击hash 对象时(#xx)会自动监听,所以我们遍历监听路由点,点击时实现和 hash 一样的模式,即点击时往历史中添加一条记录

线上demo: