You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3中含hash锚点的router-link失效,求Vue Router环境下的解决方案

Vue 3中Vue Router锚点路由失效问题解决方案

问题背景

我正在使用VueJS3,现有如下菜单列表:

菜单数据

const menu = [
    {ref: "../#home", name: "Home"},
    {ref: "../areas", name: "Areas"},
    {ref: "../#contact", name: "Contact"},
];

导航组件代码

<nav class="overlay-menu">
  <ul>
    <li v-for="(link, index) in menu" :key="index">
      <router-link :to="link.ref" @click="clicked">{{ link.name }}</router-link>
    </li>
  </ul>
</nav>

目前含hash锚点的router-link无法正常工作,曾改用<a :href="link.ref"></a>标签,但希望在Vue Router的上下文内解决该问题,请问是否有可行方案?


可行解决方案

1. 使用to对象格式拆分路径与锚点

Vue Router的router-link支持对象格式的to属性,将路径和锚点分开定义,能让Router正确解析锚点规则:

方式一:调整菜单数据结构

直接把路径和锚点拆分为两个字段,结构更清晰:

const menu = [
    {path: "../", hash: "#home", name: "Home"},
    {path: "../areas", hash: "", name: "Areas"},
    {path: "../", hash: "#contact", name: "Contact"},
];

模板对应修改:

<nav class="overlay-menu">
  <ul>
    <li v-for="(link, index) in menu" :key="index">
      <router-link 
        :to="{ path: link.path, hash: link.hash }" 
        @click="clicked"
      >
        {{ link.name }}
      </router-link>
    </li>
  </ul>
</nav>

方式二:直接解析原菜单数据

如果不想修改现有菜单结构,可在模板中动态拆分ref字段:

<nav class="overlay-menu">
  <ul>
    <li v-for="(link, index) in menu" :key="index">
      <router-link 
        :to="{ 
          path: link.ref.split('#')[0] || link.ref, 
          hash: link.ref.includes('#') ? `#${link.ref.split('#')[1]}` : '' 
        }" 
        @click="clicked"
      >
        {{ link.name }}
      </router-link>
    </li>
  </ul>
</nav>

2. 配置scrollBehavior实现锚点滚动

如果锚点跳转后页面未滚动到对应元素,需在Vue Router配置中添加scrollBehavior,确保锚点定位生效:

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [/* 你的路由配置 */],
  scrollBehavior(to, from, savedPosition) {
    // 处理锚点滚动
    if (to.hash) {
      return {
        el: to.hash,
        behavior: 'smooth' // 可选,开启平滑滚动
      }
    }
    // 其他情况回到顶部或恢复之前的滚动位置
    return savedPosition || { top: 0 }
  }
})

3. 手动调用router.push处理点击事件

若上述方案仍有问题,可在点击事件中手动调用router.push,明确控制路由跳转:

import { useRouter } from 'vue-router'

const router = useRouter()
const clicked = (link) => {
  const [path, hash] = link.ref.split('#')
  router.push({
    path: path || '/',
    hash: hash ? `#${hash}` : ''
  })
}

模板修改为:

<nav class="overlay-menu">
  <ul>
    <li v-for="(link, index) in menu" :key="index">
      <router-link 
        :to="link.ref" 
        @click.prevent="clicked(link)"
      >
        {{ link.name }}
      </router-link>
    </li>
  </ul>
</nav>

内容的提问来源于stack exchange,提问作者Maik Lowrey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 22:25:26