前端路由hash、history的实现
前言
这个坑,已经埋在笔者的待办事项里很久,就好比一滴酱油滴在白色的桌子上,现在有时间了,很想把它“擦掉”
正文
前端路由实现有两种,一是 hash,另一种是 histroy。
hash 原本是为了定位,笔者印象中最开始是 PC 端商城的楼层,点击跳转到某一模块
history 是 HTML5 新出的 API,它属于 bom。通过 history 对象可以操作浏览器的会话历史以及向前向后跳转
笔者是 React 开发者,Vue 好久没用了,所以以下内容是以 React 的角度描写
前端开发——React 全家桶——路由采用第三方库 react-router 和—— react-router 的底层是 history 库
我们在写 react 的路由写法时,通常为两种,hash 和 history ,使用它的本质是 history 库
笔者在这里写个简单的
hash 模式
它的本质是通过监听hash变化事件来修改路由内容
<body>
<a href="#/home">Home</a>
<a href="#/user">User</a>
<a href="#/about">About</a>
<div id="view"></div>
</body>
<script>
function onHashChange() {
const view = document.getElementById("view");
switch (location.hash) {
case "#/home":
view.innerHTML = "Home";
break;
case "#/user":
view.innerHTML = "User";
break;
case "#/about":
view.innerHTML = "About";
break;
default:
view.innerHTML = "Home";
break;
}
}
window.addEventListener("hashchange", onHashChange);
</script>
history 模式
看了 hash 模式,我们会觉得很简单,无非是监听 hash 的变化,现在我们再看 history 模式
<body>
<a href="/home">Home</a>
<a href="/user">User</a>
<a href="/about">About</a>
<div id="view"></div>
</body>
<script>
const elements = document.querySelectorAll("a[href]");
elements.forEach((el) =>
el.addEventListener("click", (e) => {
e.preventDefault();
const test = el.getAttribute("href");
history.pushState(null, null, el.getAttribute("href"));
onPopState();
})
);
function onPopState() {
const view = document.getElementById("view");
switch (location.pathname) {
case "/home":
view.innerHTML = "Home";
break;
case "/user":
view.innerHTML = "User";
break;
case "/about":
view.innerHTML = "About";
break;
default:
view.innerHTML = "Home";
break;
}
}
window.addEventListener("popstate", onPopState);
</script>
无非是把 hashchange 改成了 popstate,当 history 对象变化时,会出发 onPopState 事件,而我们的 history 模式不想 hash 模式那样,点击hash 对象时(#xx)会自动监听,所以我们遍历监听路由点,点击时实现和 hash 一样的模式,即点击时往历史中添加一条记录
线上demo: