原理介绍
最核心是实现:页面局部刷新和url变化而不跳转
从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
在HTML5的historyAPI出现之前,前端的路由都是通过hash来实现的,hash能兼容低版本的浏览器。Web服务并不会解析hash,也就是说#后的内容Web服务都会自动忽略,但是JavaScript是可以通过window.location.hash读取到的,读取到路径加以解析之后就可以响应不同路径的逻辑处理。
history是HTML5才有的新API,可以用来操作浏览器的session history(会话历史)。基于history来实现的路由可以和最初的路径规则一样,即不带#。用户可能都察觉不到该访问地址是Web服务实现的路由还是前端实现的路由。
关于histroy
上面提到了,history 是html5后的新方法。
window.history.back() : 后退,类似浏览器的回退
window.history.forward():前进
window.history.go(-1): 跳到前一步
window.history.length: url的队列
这里很明显了,window.history 就是记录web浏览器的历史记录的一个堆栈
看图说话:
有三个页面,打开index.html 后,通过a标签跳转到了 page2.html,再在page2.html的a标签,跳转到了 page3.html
\
这时候的
调用window.history.back() ,指针就往下走,读取page2.html
现在明白了一般情况,那我们怎么实现页面局部刷新和url变化而不跳转?
就要用到 history.pushState 和 popstate
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>test router</title>
<script type="text/javascript" src="http://s.thsi.cn/cb?js/jquery-1.9.0.js"></script>
<link rel="stylesheet" href="" />
</head>
<body>
<div>当前页面:</div>
<div id="box">
<a href="javascript:;" id="toindex">index</a>
<a href="javascript:;" id="toPage2">page2</a>
<a href="javascript:;" id="toPage3">page3</a>
</div>
</body>
<script>
// 把文字高亮为红色
function setRed(id) {
var links = $("#box").find("a");
for (var i = 0; i < links.length; i++) {
var linkId = links[i].id;
if (linkId === id) {
links[i].style.color = "red";
} else {
links[i].style.color = "black";
}
}
}
// 切换页面,对应的文字高亮,url改变
$("#box").on("click", "a", function (e) {
let currentId = $(e.currentTarget).attr("id");
window.history.pushState(
{
id: currentId,
},
"select " + currentId,
"./" + currentId
);
setRed(currentId);
});
</script>
</html>
效果如下:
可以注意到现在url在改变,而页面并没有刷新。 但是我在尝试回退的时候,发现文字并没有高亮,主要是没有监听回退后的变化
代码中再加上这段即可:
function setRed(id) {
var links = $("#box").find("a");
for (var i = 0; i < links.length; i++) {
var linkId = links[i].id;
if (linkId === id) {
links[i].style.color = "red";
} else {
links[i].style.color = "black";
}
}
}
// 切换页面,对应的文字高亮,url改变
$("#box").on("click", "a", function (e) {
let currentId = $(e.currentTarget).attr("id");
window.history.pushState(
{
id: currentId,
},
"select " + currentId,
"./" + currentId
);
setRed(currentId);
});
// 对于 pushState 回退的监听
window.addEventListener('popstate', function (e) {
setRed(e.state.id)
})
参考资料: www.jianshu.com/p/704495262…\