前言
这个坑,已经埋在笔者的待办事项里很久,就好比一滴酱油滴在白色的桌子上,现在有时间了,很想把它“擦掉”
正文
前端路由实现有两种,一是 hash,另一种是 histroy。
hash 原本是为了定位,笔者印象中最开始是 PC 端商城的楼层,点击跳转到某一模块
history 是 HTML5 新出的 API,它属于 bom。通过 history 对象可以操作浏览器的会话历史以及向前向后跳转
笔者是 React 开发者,Vue 好久没用了,所以以下内容是以 React 的角度描写
前端开发——React 全家桶——路由采用第三方库 react-router 和—— react-router 的底层是 history 库
我们在写 react 的路由写法时,通常为两种,hash 和 history ,使用它的本质是 history 库
笔者在这里写个简单的
hash 模式
它的本质是通过监听hash变化事件来修改路由内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <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 模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <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: