下面内容为阅读笔记,资料来源参考最后一部分。
核心原理
1. 什么是前端路由
在web前端单页应用SPA(Single Page Apllication)中,路由描述的是URL和UI之间的映射关系,这种映射是单向的,即URL变化引起UI更新(无需刷新页面)
2. 如何实现的前端路由
要实现前端路由,需要解决两个核心:
- 如何改变URL却不引起页面刷新?
- 如何检测URL变化?
下面分别使用hash和history两种实现方式回答上面的两个核心问题。
hash实现
hash是URL中hash(#)及后面的那部分,常用作锚点在页面进行导航,改变URL中的hash部分不会引起页面刷新。
通过hashChange事件监听URL的变化,改变URL的方式有三种:
- 通过浏览器前进后退改变URL
- 通过
<a>
标签改变URL - 通过
window.location
改变URL
history实现
history提供了pushState
和replaceState
两个方法,这两个方法改变URL的path部分不会引起页面刷新
history提供了类似hashChange事件的popstate事件,但popstate事件有些不同:
- 通过浏览器前进后退改变URL时会出发popstate事件
- 通过
pushState/repaceState
或<a>
标签改变URL不会出发popstate事件。 - 可以拦截
pushState/repaceState
的调用和<a>
标签的点击事件来检测URL变化 - 通过js调用
history
的back
,go
,forward
方法触发该事件
所以监听URL变化可以实现,只是hashChange方便。
原生JS实现前端路由
hash实现
<body>
<div>
<a href="#/js">JS</a>
<a href="#/vue">VUE</a>
<!-- 根据不同路由显示不同的内容 -->
<div id="router-view"></div>
</div>
<script>
let routerView = document.getElementById('router-view');
window.addEventListener('hashchange', () => {
routerView.innerHTML = `这是hash- ${location.hash} 对应的UI`;
});
window.addEventListener('DOMContentLoaded', () => {
if(!location.hash) {
location.hash = '/';
}
else {
routerView.innerHTML = `这是hash- ${location.hash} 对应的UI`;
}
})
</script>
</body>
history实现
<body>
<div>
<a href="/js">JS</a>
<a href="/vue">VUE</a>
<!-- 根据不同路由显示不同的内容 -->
<div id="router-view"></div>
</div>
<script>
let routerView = document.getElementById('router-view');
window.addEventListener('DOMContentLoaded', load);
window.addEventListener('popstate', ()=>{
routerView.innerHTML = location.pathname
})
function load() {
routerView.innerHTML = ${location.pathname};
var linkList = document.querySelectorAll('a[href]')
linkList.forEach(el => el.addEventListener('click', function (e) {
e.preventDefault()
history.pushState(null, '', el.getAttribute('href'))
routerView.innerHTML = location.pathname
}))
}
</script>
</body>