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

Nuxt3中哈希变更时scrollBehavior未触发的问题排查与解决

问题

我有一个Nuxt3应用,通过插件修改scrollBehavior,插件文件为plugins/router.scrollBehavior.js,代码如下:

export default defineNuxtPlugin((nuxtApp) => {
    nuxtApp.$router.options.scrollBehavior = (to, from, savedPosition) => {
        console.log('scroll')
        if (savedPosition) return savedPosition

        if (from && from.path == to.path && to.hash) {
            const hash = to.hash.replace('#', '')
            const el = document.querySelector(`[id="${hash}"]`)
            if (!el) return

            if ('scrollBehavior' in document.documentElement.style) {
                return { left: 0, top: el.offsetTop - 100, behavior: 'smooth' }
            } else {
                return { left: 0, top: el.offsetTop - 100 }
            }
        }

        return { left: 0, top: 0, behaviour: 'smooth' }
    }
})

页面包含多个带ID的锚点及对应的目录链接,链接使用<NuxtLink :to="{hash: '#id'}">。页面加载时scrollBehavior可正常触发(控制台能打印'scroll'),但点击目录链接或通过$router.push({ hash: '#id' })编程式跳转时,页面虽发生滚动,但scrollBehavior未被触发。请问这是什么原因?如何在同页面哈希变更时触发scrollBehavior?

原因

Vue Router(Nuxt3基于该路由库)默认仅在路径发生变化时触发scrollBehavior,当仅变更URL的哈希部分(同页面内锚点跳转)时,会直接使用浏览器原生锚点滚动逻辑,跳过自定义的scrollBehavior函数。

解决方法

方法1:通过Nuxt配置强制触发哈希变更时的scrollBehavior

在nuxt.config.ts中添加路由配置,让Vue Router在哈希变化时也执行自定义滚动逻辑:

export default defineNuxtConfig({
  router: {
    options: {
      scrollBehaviorOptions: {
        hashMode: 'manual' // 关键配置:禁止浏览器原生哈希滚动,强制调用scrollBehavior
      }
    }
  }
})

方法2:手动监听哈希变化执行滚动逻辑

如果方法1不生效,可以在插件中额外添加路由监听,手动处理同页面哈希跳转的滚动:

export default defineNuxtPlugin((nuxtApp) => {
    // 保留原有scrollBehavior配置
    nuxtApp.$router.options.scrollBehavior = (to, from, savedPosition) => {
        console.log('scroll')
        if (savedPosition) return savedPosition

        if (from && from.path == to.path && to.hash) {
            const hash = to.hash.replace('#', '')
            const el = document.querySelector(`[id="${hash}"]`)
            if (!el) return

            const scrollOpt = { left: 0, top: el.offsetTop - 100 }
            if ('scrollBehavior' in document.documentElement.style) {
                scrollOpt.behavior = 'smooth'
            }
            return scrollOpt
        }

        return { left: 0, top: 0, behavior: 'smooth' } // 修正原代码拼写错误:behaviour → behavior
    }

    // 客户端环境下监听哈希变化,手动触发滚动
    if (process.client) {
        nuxtApp.$router.afterEach((to, from) => {
            if (from.path === to.path && to.hash) {
                const hash = to.hash.replace('#', '')
                const el = document.querySelector(`[id="${hash}"]`)
                if (!el) return

                const offsetTop = el.offsetTop - 100
                const scrollConf = { left: 0, top: offsetTop }
                if ('scrollBehavior' in document.documentElement.style) {
                    scrollConf.behavior = 'smooth'
                }
                window.scrollTo(scrollConf)
            }
        })
    }
})

内容的提问来源于stack exchange,提问作者Cyril N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:52:33