一、存在的问题
- 刷新网页后,可能会报404(尤其是VSCode使用live server插件预览,因为该html文件没有与端口绑定)
- 开始时,需要重定向到一个路由
二、原理
- 通过监听
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>History Router Demo</title>
<style>
#root {
text-align: center;
}
.comment {
color: red;
}
</style>
</head>
<body>
<div id="root">
<div class="navbar">
<span class="link" data-href="/home">首页</span>
<span class="link" data-href="/article">文章</span>
<span class="link" data-href="/image">图片</span>
<span class="link" data-href="/comment">评论</span>
</div>
<div class="routerView">
我是首页
</div>
</div>
<script type="module">
const router = {
'/notFound': "<div>404 Not Found</div>",
'/home': `我是首页`,
'/article': `<p>这是一个段落。</p>
<p>这是一个段落。</p>
<p>这是一个段落。</p>`,
'/image': `<img src="https://www.runoob.com/images/logo.png" width="258" height="39" />`,
'/comment': `<div class="comment">这是一条评论</div>`,
};
class HistoryRouter {
constructor(router, viewContainer) {
this.router = router;
this.viewContainer = viewContainer;
this.historyStack = ['/home']; // 历史记录
this.replace({pathname: '/home', search: '', state: null}); // 重定向一下
this.setTemplate();
}
get stack() {
return this.historyStack;
}
set stack(newValue) {
this.historyStack = newValue;
this.setTemplate();
}
setTemplate() {
const length = this.historyStack.length;
const pathname = this.historyStack[length - 1] || '/notFound';
this.viewContainer.innerHTML = this.router[pathname];
}
push({ pathname, search, state }) {
window.history.pushState(state, "", pathname + search);
this.stack = [...this.stack, pathname];
}
back() {
window.history.back();
const length = this.stack.length;
if (length > 0) {
this.stack = this.stack.slice(0, length - 1);
}
}
replace({ pathname, search, state }) {
window.history.replaceState(state, "", pathname + search);
const length = this.stack.length;
if (length > 0) {
const stackCopy = this.stack.slice(0, length - 1);
stackCopy.push(pathname)
this.stack = stackCopy;
}
}
}
(function () {
const routerView = document.querySelector('.routerView');
const historyRouter = new HistoryRouter(router, routerView);
const links = document.getElementsByClassName('link');
for (const link of links) {
link.addEventListener('click', (e) => {
const href = e.target.getAttribute('data-href');
historyRouter.replace({ pathname: href, search: window.location.search, state: null });
})
}
})();
</script>
</body>
</html>