Code前端首页关于Code前端联系我们

一、hash模式在vue-router里扮演啥角色?

terry 2小时前 阅读数 3 #Vue
文章标签 router;hash模式

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(比如pushStatereplaceState)来改变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模式有哪些优缺点?

先聊优点:

  1. 兼容性强:对老浏览器友好,IE8以上都能跑,在一些企业级项目里很实用。
  2. 部署简单:不用后端配置,把打包后的文件丢到服务器,访问根路径就能正常跳转路由,不会出现404。
  3. 无刷新体验:hash变化时页面不刷新,用户切换路由时感觉很流畅,和原生App的切换体验接近。

但缺点也很明显:

  1. URL不美观:带个号,对追求URL简洁的项目来说不够优雅,比如做官网、对外宣传的页面,用户看到带#的URL可能觉得不专业。
  2. 锚点冲突风险:如果页面里要做锚点定位(比如a href="#top"回到顶部),和路由的hash会冲突,因为两者都用,这时候得自己写逻辑区分,比如路由用#/xxx,锚点用#top,再通过JS处理点击事件,不然点锚点可能触发路由跳转,搞出意外bug。
  3. 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前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门