做Vue项目的时候,路由模式选hash还是history?这俩模式到底有啥区别?啥场景用哪个更合适?今天就把Vue Router里hash和history模式的门道掰开揉碎讲清楚,帮你选对路由模式~
hash模式和history模式,底层原理有啥不同?
先从技术原理说起,hash模式靠的是URL里的哈希符(#) 玩花样——浏览器URL中#后面的内容就是hash值,比如http://xxx.com/#/home
里的/home
,Vue Router的hash模式,是监听浏览器的onhashchange
事件来实现路由切换的,只要#后面的内容变了,这个事件就会触发,Vue Router就能知道“该换组件啦”,而且整个过程页面不会刷新,因为浏览器觉得#后面的变化不算真正的URL变化,自然不会重新请求服务器~
而history模式呢?它依赖HTML5新增的History API ,核心是history.pushState()
和history.replaceState()
这两个方法,通过这俩方法,能在不刷新页面的情况下修改浏览器的历史记录,同时让URL跟着变,比如从/home
跳到/about
,调用pushState
后,URL变成/about
,页面却没刷新,不过history模式得浏览器支持HTML5的History API才行,好在现在主流浏览器早就都支持了~
看URL就知道区别?它们的URL表现差在哪?
光看URL长啥样,就能直观区分俩模式!
hash模式的URL长这样:https://yourdomain.com/#/about
—— 有个显眼的#符号,像网址后面挂了个“小尾巴”,而history模式的URL是https://yourdomain.com/about
,和传统网站的URL结构一模一样,没有额外符号,视觉上更简洁美观,用户看了也觉得“这网址正规”~
路由切换时,两者的工作逻辑有啥不一样?
路由切换的时候,俩模式的“脑回路”差别还挺大~
hash模式下,不管是点击路由链接,还是代码里用this.$router.push
跳转,Vue Router都会先修改URL里的hash部分,浏览器一旦检测到hash变了,就会触发onhashchange
事件,Vue Router捕获到这个事件后,就会匹配对应的路由组件渲染,甚至你手动在地址栏改hash值,也会触发路由切换,很灵活~
history模式则是用pushState
方法修改历史记录栈,顺道把URL也改了,比如从/home
跳去/about
,调用pushState
后,URL变成/about
但页面不刷新,用户点浏览器的前进、后退按钮时,会触发popstate
事件,Vue Router靠监听这个事件来切换路由,不过要注意:pushState
本身不会触发popstate
,所以如果是代码里主动跳转(比如this.$router.push
),Vue Router内部会自己处理状态匹配;但要是用户手动输URL回车,这时候就得服务端帮忙兜底(后面部署部分会讲)~
对SEO友好度,两者能打平手吗?
SEO(搜索引擎优化)这块,俩模式差距还不小~
hash模式有点“吃亏”:搜索引擎爬虫抓取网页时,一般会忽略#后面的内容,比如http://xxx.com/#/article
,爬虫可能只抓http://xxx.com/
,后面的路由信息直接丢了,导致路由对应的页面内容没法被正确索引,要是项目需要SEO(比如做面向用户的官网、博客),hash模式天生就不占优势。
history模式的URL是正常路径形式(比如http://xxx.com/article
),爬虫能直接抓到完整URL和页面内容,但有个前提:如果项目是纯前端SPA(没做服务端渲染或静态化),直接访问http://xxx.com/article
可能会404(因为服务端没对应的资源),这时候得配合服务端做渲染(比如用Nuxt.js做SSR),或者把项目部署到支持History API的托管平台(像Vercel、Netlify这类对SPA很友好),所以想做SEO,优先选history模式+服务端支持;要是对SEO没要求(比如内部系统),hash模式也够用~
项目部署时,两个模式踩的坑不一样?
部署环节,俩模式的“脾气”完全不同~
hash模式部署超简单:因为hash部分的变化不会让浏览器向服务器发请求,不管你把项目丢到nginx、apache这类静态服务器,还是托管平台,只要把打包后的文件丢上去,配置好入口HTML,就能正常访问,就算用户刷新页面,浏览器也只会请求index.html
,前端路由自己处理hash部分,根本不会出现404~
history模式部署就得“多操心”:用户访问https://yourdomain.com/about
这样的URL时,刷新页面或直接输URL,浏览器会向服务器请求/about
这个资源,要是服务器没对应的路由配置,直接返回404,所以必须让服务器把所有路由请求都重定向到index.html
,让前端路由来兜底,比如用nginx的话,得配置try_files $uri $uri/ /index.html;
,把找不到的资源全指向入口HTML,要是部署到Vercel、Netlify这些平台,它们对SPA有内置支持,会自动处理;但自己搭服务器的话,就得手动配,不然刷新就报错~
实际项目里,到底选hash还是history?
选模式得看项目需求,总结几个常见场景:
- 追求URL美观+能处理部署配置 → 选history模式,比如做面向C端的官网、博客,用户在意URL颜值,还需要SEO,优先history(记得配合服务端或托管平台)。
- 部署环境复杂+不想折腾服务器 → 选hash模式,比如公司内部的后台系统,用户都是员工,不需要SEO,hash模式部署简单,不容易踩坑。
- 浏览器兼容性要求高 → 优先hash模式,hash模式支持更老的浏览器(比如IE9及以上),因为
onhashchange
事件兼容性好;history模式依赖HTML5的History API,IE9及以下不支持,不过现在很多项目不用考虑这么老的浏览器,这点影响没那么大~
说到底,hash和history模式没有绝对的好坏,关键是结合URL美观需求、SEO要求、部署成本、浏览器兼容性 这些因素选,把两者的原理和差异吃透,开发时才能少踩坑,让路由模式真正服务于项目~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。