[Vuetify]クリックされた位置が要素の中か、外かを簡単に判別する方法[Vue.js, v-click-outside]

[Vuetify]クリックされた位置が要素の中か、外かを簡単に判別する方法[Vue.js, v-click-outside]

この記事は Vue 2.x 系、 Vuetify 2.x 系 を対象とした記事になります。
2022年3月、Vue 3.x 系統に対応した Vuetify 3 Beta がリリースされました
Vuetify 3 Beta のインストールを試してみた記事もありますので、ぜひそちらもご覧ください。

対象の記事Vuetify3 Betaをインストールしてみた件

今回は久しぶりに、Vuetify関連の記事です。

いつもVuetifyの記事を書く際は、だいたい何らかのUIコンポーネントについて書くことが多いですが、
今回はVuetifyに存在している、状態検知用に使える便利な機能について、です。

具体的には、「クリックされた位置が要素の中か、外か」を簡単に判定できる
v-click-outside というものについて、書いていきたいと思います。

Vuetifyの導入方法について等は、以前の記事:
[Vue.js]Vuetify のUIコンポーネントを使ってみる[v-slide, v-caroucel編]CDN経由での導入方法を、
[Vue.js] Vuetify を導入して Material Design をスマートに取り入れる方法 内に、CLI経由での導入方法 をご紹介しています。あわせてご覧ください。

v-click-outside で、クリック位置が要素の中か、外なのかを判定

このセクションのタイトルどおり、
Vuetifyでは、v-click-outside を使うと「クリックされた位置が要素の中か、外か」という状態を簡単に判定することができます。
どう使うかというと、例えば次の様に書きます。

[html側]

<div style="margin: 2rem auto; padding: 3rem;">
  <v-card
    height="200"
    width="300"
    elevation="3"
    v-click-outside="myClickOutside"
    @click="clickedOutside = false"
  >
    <template v-if="!clickedOutside">
      このカード内がクリック
    </template>
    <template v-else>
      このカード外がクリック
    </template>
  </v-card>
</div>

↑タグは何でもいいのですが、
例として2行目の v-card に、v-click-outside を指定。
条件を満たしたら実行する関数myClickOutsideを
v-click-outside=”myClickOutside” として渡しています。

その関数myClickOutsideは、例えば次のように書きます。

[JavaScript側 | methodsに定義を想定]

methods: {
  myClickOutside() {
    this.clickedOutside = true;
  },
...(省略)...
},
...(省略)...

↑関数が実行されると、 clickedOutside という data が trueになり、
上のhtml内の9〜14行目にある条件の
v-else側の条件が満たされるため、
v-card内の文言が「このカード外がクリック」に変化する、というわけです。

この例では単純に v-card 内の文言を変化させているだけですが、

この仕組みを応用して、実行される関数内に他にもいろいろ実行される事を書いておけば、
例えば自作のモーダルを開いている時に、モーダル外のクリックが起こった時に何かさせるなど、
いろいろ使い道がありそうですね。

dataは次の様に、true | false を受け取るものを定義しておけば良いです。

[JavaScript側 | data ]

 data: () => ({
   clickedOutside: false
 }),

補足:html部分をもうすこし簡潔に書く場合

上のセクションでは、v-if, v-else を使って
条件を満たした時の記述を書きましたが、これは次の様に書いても動きます。

<div style="margin: 2rem auto; padding: 3rem;">
  <v-card
    height="200"
    width="300"
    elevation="3"
    v-click-outside="myClickOutside"
    @click="clickedOutside = false"
  >
    {{ clickedOutside ? 'このカード外がクリック' : 'このカード内がクリック' }}
  </v-card>
</div>

↑9行目をご覧ください。
かなり簡潔に(6行が1行に)なりましたね。

v-if、v-else は次の様に置き換えることができる、というわけです。

<template v-if="!clickedOutside">
  このカード内がクリック
</template>
<template v-else>
  このカード外がクリック
</template>

↓ ↓ ↓

{{ clickedOutside ? 'このカード外がクリック' : 'このカード内がクリック' }}

この
条件 ? trueの場合 : falseの場合
という書き方は「三項演算子」というものを使った書き方ですが
これを使った v-if ~ v-else の置き換えは、
実際の制作現場でもよく目にする書き方ですので、もしかしたら覚えておくと役にたつかもしれません。

公式の解説ページなど

v-click-outside の、Vuetify公式ページは次になります。
クリックアウトサイド・ディレクティブ — Vuetify

また、上のセクションで少し触れた「三項演算子」については、
ご存知、Web制作に関するオンラインリファレンス、MDN(Mozilla運営)内に詳しい解説ページがあります。
条件(三項)演算子 – JavaScript | MDN

この記事のまとめ

今回は、Vuetifyの便利な機能の中から
「クリックされた位置が要素の中か、外か」を簡単に判定することができる
v-click-outside について、ご紹介しました。

記事中段でも書きましたが、この v-click-outside
地味な様でいて、結構使い道がある機能だと思います。

またこの v-click-outside ですが、
Vuetifyの v-menu や v-dialog 等のUIコンポーネントでも内部的に使用されているとのことです。
それらのコンポーネントの挙動を改めてよく見てみることで、
活用方法についての知見が得られるかもしれません。

当サイトでは、今後もVue.js、Vuetifyに関する記事を書いていく予定です。

※この記事は、内容の品質向上を目的に、随時更新を行う場合があります。