🔗

Nuxt.js: NuxtLink, aタグ の使いどき

2021/03/31に公開1

基本

<NuxtLink>

Nuxt.js でWebサイトを作成する際に、同じサイト内の別ページへのリンクには <NuxtLink> コンポーネントを使用する。

<template>
  <NuxtLink to="/about">About Page</NuxtLink>
</template>

<a>

Twitter、YouTubeなど、別サイトへのリンクには、通常通り <a> タグをそのまま使用する。

<template>
  <a href="https://twitter.com/amotarao">My Twitter</a>
</template>

同じドメインでの特殊な管理状況での使い分け

同じドメインでのページでも、一部のみまたは複数の特設ページで Nuxt.js のプロジェクトを使い分けている場合、別サイトの扱いと同様になる。

例:
https://example.com/
 |- index.html              <- Nuxt.js プロジェクトA
 |- about/index.html        <- Nuxt.js プロジェクトA
 |
 |- special/                <- Nuxt.js プロジェクトB
     |- index.html          <- Nuxt.js プロジェクトB
     |- form/index.html     <- Nuxt.js プロジェクトB
     |
     |- super/              <- Nuxt.js プロジェクトC
         |- index.html      <- Nuxt.js プロジェクトC
         |- star/index.html <- Nuxt.js プロジェクトC

同じプロジェクト内のリンクは NuxtLink、プロジェクトを跨ぐページのリンクは <a> と使い分ける。
また、nuxt.config.jsrouter.base を設定するはずで、ページにはそれぞれに合わせた <base> タグが挿入されている。
下記を参考に実装の上、リンク先が想定と正しい動作をしているかをよく確認すること。

<!-- プロジェクトC で プロジェクトA内 /about へのリンクを追加 -->
<template>
  <div>
    <!-- NG: /special/super/about を表示しようとする (VueRouter によって) -->
    <NuxtLink to="/about">About</a>

    <!-- NG: /special/super/about に遷移する (<base> によって) -->
    <a href="/about">About</a>

    <!-- NG: /special/super/https://example.com/about を表示しようとする (VueRouter によって) -->
    <NuxtLink to="https://example.com/about">About</a>

    <!-- OK -->
    <a href="https://example.com/about">About</a> 
  </div>
</template>

<NuxtLink>, <a> を出し分けする

リンクにスタイルなどを付与したコンポーネントを作ることはよくあることである。
タグ名(コンポーネント名)を入れ替えるために <component is=""> が利用できる。

props で指定

タグ名をそのまま <component>is に入るようにする。

<tempate>
  <component
    :is="tag"
    class="link"
    :href="tag === 'a' ? url : undefined"
    :to="tag !== 'a' ? url : undefined"
  >
    <slot />
  </component>
</tempate>

<script>
export default {
  props: {
    url: {
      type: String,
      required: true,
    },
    tag: {
      type: String,
      default: 'a',
      validator: (tag) => ['a', 'NuxtLink'].includes(tag),
    },
  },
};
</script>

computed で判定

URL が外部のものかを判定し、自動でタグを切り替えるようにする。
例は urlhttp:// または https:// の場合に外部リンクと判定するものである。

<tempate>
  <component
    :is="isExternal ? 'a' : 'NuxtLink'"
    class="link"
    :href="isExternal ? url : undefined"
    :to="!isExternal ? url : undefined"
  >
    <slot />
  </component>
</tempate>

<script>
export default {
  props: {
    url: {
      type: String,
      required: true,
    },
  },
  computed: {
    isExternal() {
      return this.url.match(/^https?:\/\//);
    },
  },
};
</script>

Discussion

amonamon

なぜ undefined ?

<template>
  <div>
    <!-- NG: クリックイベントでリンクとしては機能するが、href が空になりアクセシビリティを損なう -->
    <NuxtLink to="/about" href="">About</NuxtLink>
    <!-- NG: クリックイベントでリンクとしては機能するが、href が消えてアクセシビリティを損なう -->
    <NuxtLink to="/about" :href="null">About</NuxtLink>

    <!-- OK: href が "/about" になる (必要なときだけにする) -->
    <NuxtLink to="/about" :href="undefined">About</NuxtLink>
    <!-- OK: href が "/about" になる -->
    <NuxtLink to="/about">About</NuxtLink>
  </div>
</template>