BLOG

ブログ

【Nuxt.js】NuxtLinkでクリックイベントをカスタマイズする

こんにちはタロウです。

NuxtLinkでrouter機能を動かさずにクリックイベントをカスタマイズし実行することができたので、その方法を紹介します。

実現したいこと

弊社のコーポレートサイトですが、
フッターメニューは全てNuxtLinkでリンク配置しています。

例えば、/about を開いている場合にABOUT USリンクを押し、
ページ先頭へスムーススクロールなどページ内処理を行いたい場合、
NuxtLinkをそのまま使用すると遷移先が同じページのため、
何も発火せずスクロールさせることができません。

▲このような動きとなり、リンク毎にDOMを変更しないといけなくなってしまいます。

クリックイベントで任意メソッドを呼び出し解決

まずNuxtLinkへクリックイベントを拾えるよう@click.nativeでメソッドを指定します。

この状態ではメソッドは実行されるようになりますが、
vue-routerが生きているのでメソッド実行後にtoで指定したパスへ遷移してしまいます。

そのため、NuxtLink引数のeventをevent=””としvue-routerを無効化します。
(無効化というよりイベントを空で上書きするイメージです)

全体の実装例はこのようになります。

<template>
  <nuxt-link :to="linkTo" event="" @click.native="onClick" />
</template>
<script>
export default {
  name: 'CommonInternalLink',
  methods: {
    /**
     * クリックイベント
     */
    onClick() {
      // 処理させたいイベント
      // スムーススクロールとか
    },
  },
}
</script>
<style lang="scss" scoped></style>

▲シンプルなNuxtLinkのみのコンポーネント

ベストだと考えるNuxtLinkのコンポーネント

サイト内で使う箇所が多くなりますが、
NuxtLinkだけを持つコンポーネントを作成し、現在ページかどうかでクリック時のアクションを切り替えます。

<template>
  <nuxt-link
    v-if="isSameRoute"
    :key="linkKey"
    :to="linkTo"
    event=""
    @click.native="onClick"
    >
    <slot></slot>
  </nuxt-link>
  <nuxt-link v-else :key="linkKey" :to="linkTo">
    <slot></slot>
  </nuxt-link>
</template>
<script>
export default {
  name: 'CommonInternalLink',
  props: {
    linkKey: {
      type: String,
      default: '/',
      required: false,
    },
    linkTo: {
      type: String,
      default: '/',
      required: true,
    },
  },
  computed: {
    /**
     * 現在パスと遷移先パスの同一判定
     */
    isSameRoute() {
      return this.linkTo === this.$route.path
    },
  },
  methods: {
    /**
     * クリックイベント
     */
    onClick() {
      // スクロールの処理とか遷移先のページが現在ページと同じ場合
    },
  },
}
</script>

算出プロパティでリンクごとにアクションを切り分け、NuxtLinkを設置します。
また、コンテンツはslotで表現しているのでテキストでも画像でもdivそのものでも対応できるようにしています。

さいごに

弊社コーポレートサイトのリニューアルの際に悩んだNuxtLinkでクリックイベントをカスタマイズし実行する方法でした。

実現するにあたりなかなかピンポイントで解決例を見つけることができなかったので、
誰かのヒントになればと思います!