单页面SPA应用路由原理 history hash
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>单页面SPA应用路由原理</title>
<style type="text/css">
.api,
.hash {
color: blue;
display: block;
cursor: pointer;
}
</style>
</head>
<body>
<a class='api a'>a.html</a>
<a class='api b'>b.html</a>
<p>
</p>
<a class='hash a'>#a.html</a>
<a class='hash b'>#b.html</a>
<script type="text/javascript">
// 注册路由
// 说明:document.querySelectorAll('.api') 返回的是类数组对象NodeList,这个NodeList可以使用数组的方法forEach
// NodeList只有数组的forEach方法,其他方法map/filter等方法没有
document.querySelectorAll('.api').forEach(item => {
item.addEventListener('click', (e) => {
// 阻止默认事件
e.preventDefault();
let link = item.textContent;
// pushState有3个参数,第一个参数是跳转url的状态信息,第二个参数是页面标题,第三个参数是跳转链接
//
window.history.pushState({
name: 'api'
},
'页面标题',
link
)
}, false) // false 表示冒泡阶段执行
});
// 监听路由
// popstate 属于window事件
window.addEventListener('popstate', (e) => {
console.log({
location: location.href,
state: e.state
})
})
// 注册路由
document.querySelectorAll('.hash').forEach(item => {
item.addEventListener('click', (e) => {
e.preventDefault();
let link = item.textContent;
window.location.hash = link
}, false)
});
// 监听路由
// hashchange 属于window事件
window.addEventListener('hashchange', (e) => {
console.log({
location: location.href,
state: e.state
})
})
// hash改变的方法:
// window.location.assign('#a')
// window.location.replace('#b')
</script>
</body>
</html>
说明:pushstate和replacestate不能监听到路由变化,可以重写pushstate和replacestate,这样就获取到了pushState 和 replaceState 的参数。
// Add this: var _wr = 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 = _wr('pushState'); history.replaceState = _wr('replaceState'); // Use it like this: window.addEventListener('pushState', function(e) { console.warn('THEY DID IT AGAIN!'); }); window.addEventListener('replaceState', function(e) { console.warn('THEY DID IT AGAIN!'); });
hash和history的区别:
hash:
(1)丑
(2)hash会占用锚点功能
(3)兼容性较好
history:
(1)路由与后端无异
(2)IE10级以上
(3)需要后端支持
(4)popstate仅仅在前进或者后退时才触发。
onpopstate
作者:孟繁贵 Email:meng010387@126.com 期待共同进步!