一、hash模式在vue-router里扮演啥角色?
p标签开头:想要搞懂vue-router里的hash模式,得先从前端路由的逻辑说起,很多人做单页应用时,发现URL里总有个#号,切换页面还不刷新,这背后就是hash模式在起作用,今天咱们就把hash模式的原理、用法、优缺点这些事儿掰开了揉碎了讲清楚。
前端路由的核心是“不刷新页面就能切换内容”,hash模式就是vue-router实现前端路由的一种方式,举个例子,传统多页应用点击链接会请求新页面,页面整个刷新;但单页应用要的是“局部更新”,这时候hash模式通过URL里的#号做文章——#后面的内容变化时,浏览器不会真的向服务器发请求,只是触发hashchange
事件,vue-router监听到这个事件后,就会匹配对应的路由规则,把对应的组件渲染到页面上,简单说,hash模式是让单页应用实现“无刷新跳转”的关键手段之一,不用麻烦后端同学配合,自己在前端就能搞定路由切换。
hash模式的工作原理是啥?
得先理解URL里的hash是啥,比如https://xxx.com/#/home
,#/home
就是hash部分,浏览器有个特点:当URL的hash变化时(比如从#/home
变到#/about
),它不会发起HTTP请求去刷新页面,但会触发window
上的hashchange
事件,vue-router正是利用了这个机制——它在内部监听hashchange
,一旦检测到hash变了,就去路由规则里找对应的组件配置,然后更新页面上的视图。
举个实际开发的例子,你在代码里写了<router-link to="/user">用户页</router-link>
,点击后URL的hash会变成#/user
,vue-router监听到这个变化,就把User
组件渲染到<router-view>
的位置,整个过程页面没刷新,用户体验很流畅。
hash模式和history模式有啥不同?
这俩都是vue-router实现前端路由的方式,但区别还不少:
首先看URL长相——hash模式的URL带,比如xxx.com/#/about
;history模式的URL更“干净”,像xxx.com/about
,和传统网站URL差不多。
然后是服务器依赖——history模式需要后端配合,因为当用户直接访问xxx.com/about
这种地址时,浏览器会向服务器发请求,如果后端没配置fallback
(比如把所有路由请求指向index.html),就会返回404;但hash模式不用操心这个,因为后面的内容不会被服务器解析,不管hash怎么变,服务器收到的请求都是xxx.com/
,所以部署时不用麻烦后端改配置。
还有实现原理——hash模式靠hashchange
事件,history模式则用HTML5的history API
(比如pushState
、replaceState
)来改变URL,同时不会触发页面刷新,不过history模式能做更多事,比如修改URL的同时添加历史记录,但兼容性上hash模式更好(IE8都能支持,history模式得IE10以上)。
啥场景下适合用hash模式?
如果项目属于这几种情况,选hash模式准没错:
第一种是“后端不想配合”的情况,比如公司里后端同学忙,不想为前端路由改nginx或Apache的配置,这时候hash模式不用后端插手,自己部署就能跑通,省事儿。
第二种是“兼容性要求高”的项目,要是产品得兼容IE8、IE9这些老浏览器,hash模式的兼容性优势就体现出来了,因为hashchange
在IE8就能用,而history模式依赖的HTML5 API在老浏览器里不支持。
第三种是“快速迭代的小项目”,比如做个内部工具、Demo页面,优先要开发效率,不想在路由配置上花太多时间,hash模式开箱即用(vue-router默认就是hash模式,不用额外配置),能让你更快把功能跑起来。
如果项目追求URL美观、SEO友好(虽然单页应用SEO本身弱,但history模式的URL对爬虫更友好些),或者需要和后端做更复杂的路由配合,这时候才考虑history模式。
hash模式有哪些优缺点?
先聊优点:
- 兼容性强:对老浏览器友好,IE8以上都能跑,在一些企业级项目里很实用。
- 部署简单:不用后端配置,把打包后的文件丢到服务器,访问根路径就能正常跳转路由,不会出现404。
- 无刷新体验:hash变化时页面不刷新,用户切换路由时感觉很流畅,和原生App的切换体验接近。
但缺点也很明显:
- URL不美观:带个号,对追求URL简洁的项目来说不够优雅,比如做官网、对外宣传的页面,用户看到带#的URL可能觉得不专业。
- 锚点冲突风险:如果页面里要做锚点定位(比如
a href="#top"
回到顶部),和路由的hash会冲突,因为两者都用,这时候得自己写逻辑区分,比如路由用#/xxx
,锚点用#top
,再通过JS处理点击事件,不然点锚点可能触发路由跳转,搞出意外bug。 - SEO不友好:虽然单页应用做SEO本来就麻烦,但hash模式的URL里后面的内容不会被搜索引擎抓取(早期爬虫不解析hash),不过现在很多SEO方案(比如SSR、预渲染)能解决这个问题,所以算“相对缺点”。
在vue-router里怎么配置hash模式?
得看vue-router的版本,因为3.x和4.x的配置方式不一样:
vue-router 3.x(Vue2常用版本)
创建路由实例时,把mode
设为'hash'
就行(其实默认就是hash,不写也一样),代码长这样:
import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' Vue.use(Router) export default new Router({ mode: 'hash', // 显式配置hash模式,默认也是hash,可省略 routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: () => import('./views/About.vue') } ] })
vue-router 4.x(Vue3常用版本)
版本4把mode
属性移除了,改用createWebHashHistory
这类函数来指定路由模式,配置如下:
import { createRouter, createWebHashHistory } from 'vue-router' import Home from './views/Home.vue' const routes = [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: () => import('./views/About.vue') } ] const router = createRouter({ history: createWebHashHistory(), // 指定hash模式 routes }) export default router
不管哪个版本,配置后就能用hash模式实现路由切换,URL里自动带上,切换路由时页面也不会刷新~
hash模式下遇到的常见问题咋解决?
实际开发中,hash模式容易碰到这些坑,对应的解决思路可以参考:
锚点和路由hash冲突
比如页面里有<a href="#top">回到顶部</a>
,点击后URL的hash变成#top
,但vue-router会把它当成路由请求,可能跳转到不存在的页面,导致报错。
解决方法:
- 区分路由和锚点的hash格式,比如路由用
#/xxx
,锚点用#top
,然后在锚点的点击事件里阻止默认行为,用JS实现滚动。<a @click.prevent="goTop">回到顶部</a> <script> export default { methods: { goTop() { window.scrollTo(0, 0) } } } </script>
- 或者用
vue-scrollto
这类第三方库,更优雅地处理锚点滚动,避免和路由hash冲突。
微信分享时URL带#被截断
有些老版本的微信浏览器分享带hash的URL时,可能只保留前面的部分,导致分享后链接失效。
解决方法:
- 用JS动态处理分享链接,比如把hash部分编码,或者后端配合做301重定向,不过现在微信对hash的支持已经好很多,遇到问题时可以先测试不同机型,再针对性处理。
路由参数传递不直观
hash模式下,参数可以通过query
(显示在URL)或params
(不显示在URL,靠路由规则匹配)传递,但params
在hash模式下如果路由没定义动态段,刷新后参数会丢失。
建议:如果需要参数持久化,优先用query
,比如this.$router.push({ path: '/user', query: { id: 1 } })
,URL会变成#/user?id=1
,刷新也能保留参数;如果用params
,得确保路由配置了动态路径(如path: '/user/:id'
),且通过命名路由跳转(this.$router.push({ name: 'user', params: { id: 1 } })
),这样URL会是#/user/1
,参数也能保留。
vue-router的hash模式是前端路由里“轻量又兼容”的选择,适合追求开发效率、兼容老浏览器、不想麻烦后端的项目,虽然它有URL不美观、锚点冲突这些小缺点,但理解原理后针对性解决,完全能在项目里稳定发挥作用,要是你做项目时纠结选hash还是history,不妨先从hash模式入手,把功能跑通再根据需求调整,这样开发节奏会更顺畅~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。