event.preventDefault()
でデフォルトイベントを無効化できますが、これを全タグの@click
に定義していくのはとても大変です。
そこでクリック時にevent.preventDefault()
を実行するディレクティブを作ったのでその解説です。
そもそもそんなの必要?
基本的には使わないです。だいぶレアケースだと思います。
Stores.jpというECサービスの開発をやっているのですが、そこではストアのWeb画面を作るエディタ画面があります。
この画面では、実際のストア画面ではリンクになりますよというのを示しつつ、押しても反応しないリンクを作る必要があります。
※押して反応してしまうと、エディタ画面から移動してしまうため。
そのため、例えば<a>
のUIはそのままで、デフォルトイベントであるURLを移動するという処理だけ無効化したいのです。
膨大にあるリンク(このキャプチャには表示されていない部分でもたくさんあります)
デモ
実際のデモから見たほうがわかりやすいかと思います。
https://nuxt-sandbox.netlify.com/directives-sample/prevent-click
v-prevent-click
というディレクティブを指定して、aタグの挙動を変えています。
また汎用性を考慮して、動的に切り替えても問題がないようにしています。
つくりかた
デモ画面と同じものを作っていきます。
ディレクティブ 本体
bindフック関数 で要素のセットアップ処理を行います。
指定した=イベントを止めたい、なのでデフォルトはtrueで良いでしょう。
updateフック関数で値の変更を検知してイベントリスナーの追加、削除を行っています。
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配下に作りました。
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
へ渡す値を動的に切り替えた場合
<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