js - window.history 与 hash
零、引言
本篇是关于 window.location (history/hash) 的尝试,算是为了学习各种 router 的基础吧。
参考资料:
1. url 中的 hash;
一、基础准备
基础的 index.html 页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!DOCTYPE html> <html lang= "en" > <head> <meta charset= "UTF-8" > <meta name= "viewport" content= "width=device-width, initial-scale=1.0" > <title>js - router</title> </head> <body> <ul> <!-- 定义路由 --> <li><a href= "#/home" >home</a></li> <li><a href= "#/about" >about</a></li> <!-- 渲染路由对应的 UI --> <div id= "routeView" ></div> </ul> <!-- 不同场景下引入对应文件 --> <!-- <script src= "hash.js" ></script> --> <!-- <script src= "history.js" ></script> --> </body> </html> |
二、hash(#)
最开始是用在 a 标签的 href 中,用来跳转到页面的指定位置,当然,因为经常与 id 选择器一起使用,所以一开始经常认为单纯的是 id 选择器。在 H5 更新的标准中,它有了更多的意义。
上面参考资料中提及的需要注意的地方是 4.5.7 三点,因此也有了我们接下来的实践:
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 | // 维护 UI 页面 let routerView = null ; // 路由变化时,根据路由渲染对应的 ui 页面 function onHashChange() { switch (window.location.hash) { case '' : case '#/home' : routerView.innerHTML = 'Home' ; return ; case '#/about' : routerView.innerHTML = 'About' ; break ; default : break ; } } // 页面加载完不会触发 hashchange,这里主动触发一次 hashchange 事件。 window.addEventListener( 'DOMContentLoaded' , () => { routerView = document.querySelector( '#routeView' ); onHashChange(); }) // 监听路由变化。 window.addEventListener( 'hashchange' , onHashChange); |
三、history
history 在 H5 标准中新增了 pushState/replaceState 两个 api,这两均能够修改浏览器的历史记录,同时也方便了在写代码的过程中对页面流向的控制,不过也存在些问题,下一个章节进行比较。
先看实践:
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 37 38 | // 维护 UI 页面。 let routerView = null ; // 路由变化时,根据路由渲染对应 UI 页面。 function onPopState() { switch (window.location.pathname) { case '/' : case '/home' : routerView.innerHTML = 'Home' ; return ; case '/about' : routerView.innerHTML = 'About' ; break ; default : break ; } } // 页面加载完不会触发 onPopState, 这里主动触发一次 onPopState 事件。 window.addEventListener( 'DOMContentLoaded' , () => { routerView = document.querySelector( '#routeView' ); // 刷新页面。 onPopState(); // 拦截 <a> 标签点击事件默认行为, 点击时使用 pushState 修改 URL并更新手动 UI,从而实现点击链接更新 URL 和 UI 的效果。 let links = document.querySelectorAll( 'a[href]' ); links.forEach(el => { el.addEventListener( 'click' , e => { e.preventDefault(); // 手动拦截 window.history.pushState( null , '' , el.getAttribute( 'href' )); onPopState(); }) }) }) // 监听路由变化。 window.addEventListener( 'popstate' , onPopState); |
和 hash 的处理思路相同,调用的 api 略有区别,增加了取消 DOM 元素的原生事件步骤。
四、两者的特点
1. hash -- 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.abc.com/#/hello,hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
2. history -- 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
所以呢, 在 hash 模式下,无论怎么刷新网页,浏览器一直是请求的同一个 index.html 文件,所以服务器不需要做额外的处理,只是显示在 url 栏中不那么美观。但是在 history 模式下,前进/后退等操作也只是修改的本地浏览器的历史栈,不发请求,刷新就不同了,这个操作会实打实地去请求当前 url 对应的资源,这意味着服务器不做处理,分分钟是 404,因此 vue-router 文档中强调开启 history 需要服务器支持。
分类:
js
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码