LoginSignup
3
1

More than 5 years have passed since last update.

vue.jsでクリックのデフォルトイベントを止めるディレクティブを作る

Posted at

event.preventDefault()でデフォルトイベントを無効化できますが、これを全タグの@clickに定義していくのはとても大変です。
そこでクリック時にevent.preventDefault()を実行するディレクティブを作ったのでその解説です。

そもそもそんなの必要?

基本的には使わないです。だいぶレアケースだと思います。

Stores.jpというECサービスの開発をやっているのですが、そこではストアのWeb画面を作るエディタ画面があります。
この画面では、実際のストア画面ではリンクになりますよというのを示しつつ、押しても反応しないリンクを作る必要があります。
※押して反応してしまうと、エディタ画面から移動してしまうため。

そのため、例えば<a>のUIはそのままで、デフォルトイベントであるURLを移動するという処理だけ無効化したいのです。

膨大にあるリンク(このキャプチャには表示されていない部分でもたくさんあります)

image.png

デモ

実際のデモから見たほうがわかりやすいかと思います。
https://nuxt-sandbox.netlify.com/directives-sample/prevent-click

v-prevent-click というディレクティブを指定して、aタグの挙動を変えています。
また汎用性を考慮して、動的に切り替えても問題がないようにしています。

つくりかた

デモ画面と同じものを作っていきます。

ディレクティブ 本体

bindフック関数 で要素のセットアップ処理を行います。
指定した=イベントを止めたい、なのでデフォルトはtrueで良いでしょう。

updateフック関数で値の変更を検知してイベントリスナーの追加、削除を行っています。

/plugins/directives/prevent-click.js
function preventDefaultFunc(event) {
  event.preventDefault()
}

export default {
  bind(el, { value = true }) {
    if (value) {
      el.addEventListener('click', preventDefaultFunc)
    }
  },
  update(el, { value, oldValue }) {
    if (value !== oldValue) {
      if (value) {
        el.addEventListener('click', preventDefaultFunc)
      } else {
        el.removeEventListener('click', preventDefaultFunc)
      }
    }
  }
}

ディレクティブのロード

Nuxt.js を使っているので、plugins配下に作りました。

/plugins/directives.js
import Vue from 'vue'
import PreventClick from '~/plugins/directives/prevent-click'

Vue.directive('prevent-click', PreventClick)

コンポーネント

次の3パターンを用意して動作を確認しています。

  • v-prevent-click を指定していない場合
  • v-prevent-click を指定した場合
  • v-prevent-click へ渡す値を動的に切り替えた場合
prevent-click.vue
<template>
  <section>
    <h2>直接指定した場合の確認</h2>
    <ul class="links">
      <li>
        <a
          href="https://example.com"
          target="_blank">https://example.com</a> (no v-prevent-click)
      </li>
      <li>
        <a
          v-prevent-click
          href="https://example.com"
          target="_blank">https://example.com</a> (v-prevent-click)
      </li>
    </ul>

    <h2>有効無効の切り替えの確認</h2>
    <button
      type="button"
      @click="preventClickEnabled = !preventClickEnabled">切替</button>
    <ul class="links">
      <li>
        <a
          v-prevent-click="preventClickEnabled"
          href="https://example.com"
          target="_blank">https://example.com</a> (v-prevent-click={{ preventClickEnabled }})
      </li>
    </ul>
  </section>
</template>

<script>
export default {
  data: function() {
    return {
      preventClickEnabled: false
    }
  }
}
</script>

<style>
.links li {
  margin-bottom: 15px;
}
</style>

あとがき

全コードを公開しているので置いときます
https://github.com/howdy39/nuxt-sandbox

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1