hash模式

使用hashchange事件监听地址栏变化,从而更新dom.

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!doctype html>
<div class="main">
<a href="#personal">personal</a><br />
<a href="#search">search</a><br />
</div>
<script>
let main = document.querySelector("div.main");
window.onhashchange = (e) => {
// 获取新的地址
let path = e.newURL;
// 更新dom
main.innerHTML = path;
};
</script>

history模式

  • 劫持跳转事件
  • 使用history.pushState实现更新地址栏

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!doctype html>
<div class="main"><a href="test.html">test.html</a><br /></div>
<script>
let main = document.querySelector("div.main");
main.addEventListener("click", (e) => {
if (e.target.nodeName === "A") {
// 阻止默认跳转行为
e.preventDefault();
// 获取地址
let path = e.target.href;
// 更新地址栏
window.history.pushState({}, "", path);
// 更新dom
main.innerHTML = `${path}`;
}
});
</script>

history模式下,跳转并不会真的发送请求,但是改变了地址栏,此时刷新会导致404错误。

所以后端要重定向所有的请求到索引页面,以nginx为例:

1
2
3
4
location / {
# 告诉nginx找不到资源时如何处理
try_files $uri $uri/ /index.html;
}

这样还有一个问题,跳转后刷新一个页面会导致回到首页,失去了路由的意义,所以要在页面刚加载时读取到地址栏信息,然后根据地址渲染页面。