路由的概念来源于服务端,在服务端中路由描述的是 URL 与处理函数之间的映射关系。
在 Web 前端单页应用 SPA(Single Page Application)中,路由描述的是 URL 与 UI 之间的映射关系,这种映射是单向的,即 URL 变化引起 UI 更新(无需刷新页面)。
核心:
方法:
hashchange
事件监听URL变化,改变URL的方式: <a>
标签改变URLwindow.locatioin
改变URLpushState
和replaceState
两个方法: popstate
事件,但popstate
事件有些不同: popstate
事件pushState/replaceState
或<a>
标签改变URL时不会触发popstate
事件pushState/replaceState
的调用和<a>
标签的点击事件来检测URL是否发生变化<body>
<!-- route -->
<ul>
<li>
<a href="#/home">home</a>
</li>
<li>
<a href="#/about">about</a>
</li>
</ul>
<!-- view -->
<div id="routerView"></div>
<script>
window.addEventListener('DOMContentLoaded',onLoad)
//监听路由变化
window.addEventListener('hashchange',onHashChange)
let routerView = null;
function onLoad() {
routerView = document.querySelector('#routerView');
onHashChange();
}
function onHashChange() {
switch(location.hash) {
case '#/home':
routerView.innerHTML = 'HOME';
return;
case '#/about':
routerView.innerHTML = 'About';
return;
default:
routerView.innerHTML = '';
return;
}
}
</script>
</body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<ul>
<li>
<a href="/home">home</a>
</li>
<li>
<a href="/about">about</a>
</li>
<div id="routeView"></div>
</ul>
<script>
window.addEventListener('DOMContentLoaded',onLoad)
//监听路由变化
window.addEventListener('popstate',onPopState)
//routeView
let routeView = null;
function onLoad () {
routeView = document.querySelector('#routeView');
onPopState()
//拦截a标签点击事件,点击时使用pushState修改URL并手动更新routeView
let linkList = document.querySelectorAll('a[href]')
linkList.forEach(el => el.addEventListener('click',function(e){
e.preventDefault()
history.pushState(null,'',el.getAttribute('href'))
onPopState()
}))
}
function onPopState() {
switch (location.pathname) {
case '/home':
routeView.innerHTML = 'HOME'
return
case '/about':
routeView.innerHTML = 'About'
return
default:
routeView.innerHTML = ''
return
}
}
</script>
</body>
</html>
我们看到,使用history
的方式,需要多判断a标签点击事件并拦截。