[Nuxt.js] アンカーリンクの遷移が動作しない場合の対処方法

状況

  • ページ内アンカーリンクがある - #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でタイミングをずらしている。