などの疑問や悩みを解決してまいります。
親要素にもイベント処理を指定しており、子要素にもイベント処理を指定して各イベントを個別に実行したいのに、両方ともイベント処理が実行されてしまう…そんな現象に悩まれていませんか?
今回は、この問題の原因と解決方法について解説していきます。
子要素のイベントと親要素のイベントが同時に起きる現象例
実際にどのような問題かを確認してみましょう。
<template>
<v-container>
<v-expansion-panels multiple>
<v-expansion-panel>
<v-expansion-panel-title>
<p>タイトルが入ります</p>
<v-select
:items="selectItems"
density="compact"
label="選択してください"
class="px-4"
></v-select
></v-expansion-panel-title>
<v-expansion-panel-text>
<p>
テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。
</p>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</template>
<script setup land="ts">
const selectItems = ["選択肢1", "選択肢2", "選択肢3", "選択肢4"];
</script>
上記は、Vuetifyのコンポーネントタグを使用してアコーディオン機能の中にセレクトボックスを追加しています。
本来やりたいことはセレクトボックスをクリックすると選択ボックスだけが表示される、アコーディオン領域をクリックすると開閉処理だけが実行されることなのですが、セレクトボックスをクリックするとなぜか選択ボックスの表示と開閉処理も同時に行われてしまいます。
このようにパネル開閉と選択ボックスの表示が同時に行われてしまっているのが分かると思います。
原因:バブリング
この原因はイベントのバブリングという現象にあります。
バブリングとは、子要素のイベント発生が親要素にも順に伝播する現象のことを言います。
つまり今回起きている現象として、子要素のv-select
の選択ボックス表示イベントが親要素のv-expansion-panel
のパネル開閉イベントにも伝播してしまい、結果的に両方のイベントが発生してしまうということになります。
解決方法:@click.stop
解決方法は子要素のv-select
に対して@click.stop
のイベント修飾子を追加します。
<template>
<v-container>
<v-expansion-panels multiple>
<v-expansion-panel>
<v-expansion-panel-title>
<p>タイトルが入ります</p>
<v-select
:items="selectItems"
density="compact"
label="選択してください"
class="px-4"
@click.stop // 追加
></v-select
></v-expansion-panel-title>
<v-expansion-panel-text>
<p>
テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。テキストが入ります。
</p>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</template>
<script setup land="ts">
const selectItems = ["選択肢1", "選択肢2", "選択肢3", "選択肢4"];
</script>
追加することでイベントのバブリングを防ぐことができます。
このように親要素へのイベントの伝播を防ぐことができ、同時イベント実行の現象は改善できます。
まとめ
ここまで読んでいただきありがとうございました。
本記事のまとめです。
本記事のまとめ
- バブリングとは、子要素のイベント発生が親要素にも順に伝播する現象のこと
- 子要素に対して
@click.stop
のイベント修飾子を追加することで、バブリングを防ぐことができる