楔子
众所周知,当前前端应用最重要的一种实现方式就是单页应用。单页应用有着良好用户体验和减轻服务器的优点,单页也存在seo的相关方面问题。但是这个不是今天讨论的重点,我们今天的重点是之所以能够实现spa的效果,浏览器为我们提供哪些基础设施。
history和hash模式
history url比较优美,但是部署上线的时候需要对应的后端兼容请求不到资源的情况
hash模式兼容性比较好但是很多人认为#作为url不够优雅
有助于理解spa底层实现原理的例子
<!--
1. History的pushState replaceState 不会触发popstate事件,History的go back forward会触发,这个时候需要包装pushState 和 replaceState方法 然后派发一个事件出来进行
var _wrapper = function(type) {
var orig = history[type];
return function() {
var rv = orig.apply(this, arguments);
var e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
return rv;
};
};
history.pushState = _wrapper('pushState');
history.replaceState = _wrapper('replaceState');
-->
<ul class="history">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<script>
document.querySelectorAll(".history")[0].addEventListener('click', function (e) {
let node = e.target
if(node.tagName === 'LI'){
let value = node.textContent
history.pushState({text: value}, value, '/'+value)
}
})
window.onpopstate = function (e) {
console.log(e)
}
</script>
<!--
1. hash模式可能不太美观,但是兼容性比较好
2. 另外hash的变化会先出阿发popstate事件,然后在出发hashchange事件(注意)
-->
<ul class="hash">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<script>
document.querySelectorAll(".hash")[0].addEventListener('click', function (e) {
let node = e.target
if(node.tagName === 'LI'){
let value = node.textContent
location.hash = `#${value}`
}
})
window.onhashchange = function (e) {
console.log(e)
}
</script>