状況

  • ページ内アンカーリンクがある
    • #foo, #bar
  • アンカーリンクをクリックするとページ内遷移ではなく、ルートページに移動してしまう

原因

nuxt.config.jsに設定されているrouter.baseが原因だった(未設定でも下記のようなデフォルト値が入る)

// nuxt.config.js
export default {
  router: {
    base: '/'
  }
}

これにより、<base href="/"><head>内に追加されパスが変わってしまっているようであった。

vue-meta

Nuxt.jsにおいては、vue-routerとの兼ね合いもあり、head()(vue-meta)経由の<base>の書き換えはできない模様。

(書き換えられたとして、そちら側で問題が起きそう)

対応方法

そのままでは、先述のように<base href="/">に引っ張られてしまうため、アンカー要素に対して処理を施した。

対象のリンクに対して下記のようなイベントを付与。

element.addEventListener('click', e => {
  e.preventDefault();
  e.stopPropagation();

  setTimeout(() => {
    const target = document.querySelector(element.hash);
    if (target) {
      window.scrollTo({ left: 0, top: target.offsetTop, behavior: 'smooth' });
    }
  }, 0);
});

アンカー要素のイベントを止めて、アンカー対象の要素の位置までスクロールさせるといった処理である。
Nuxt.js側の処理とかち合うケースがあったため、setTimeoutでタイミングをずらしている。