JavaScriptのイベントは、イベントが発生した要素でのみ発生するのではなく、イベントの発生元である用途の親要素や子要素でもイベントが発生します。
イベントの伝播についての詳細は、以下の記事をご覧ください。
Vue.jsには、このイベントの伝播を抑制するための仕組みが用意されています。
そこで今回は、v-onディレクティブでイベントをバインドする際に、イベントの伝播を抑制する時に使用する.stop修飾子について紹介します。
イベントの伝播例
イベントはWebページの最上位にあるwindowオブジェクトから、DOMツリー(文書ツリー)をたどってイベントの発生元である要素まで伝播し、イベントの発生元の要素までくると、今度は逆に上位の要素の向かってイベントが伝播し、windowオブジェクトまで到達します。
例えば以下のようなHTMLテンプレートがある場合、イベントは発生元の要素に加えて、その親となる上位の要素や子となる下位の要素でも発生します。
1 2 3 4 5 6 7 8 9 10 11 |
<div id="app"> <div id="myParent" v-on:click="onClickParent"> 親要素 <div id="myElement" v-on:click="onClickMe"> 自要素 <div id="myChild" v-on:click="onClickChild"> 子要素 </div> </div> </div> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Vue.createApp({ methods: { onClickParent: function(e) { console.log('親要素のclickイベントが発生'); }, onClickMe: function(e) { console.log('自要素のclickイベントが発生'); }, onClickChild: function(e) { console.log('子要素のclickイベントが発生'); }, } }).mount('#app') |
div要素が3階層で入れ子(ネスト)の状態で配置され、それぞれの要素のclickイベントにイベントハンドラーのメソッドがバインドされています。
上記のコードをブラウザーで実行(表示)して要素をクリックすると、コンソールには次のログが出力されます。
1 2 |
自要素のclickイベントが発生 親要素のclickイベントが発生 |
1 2 3 |
子要素のclickイベントが発生 自要素のclickイベントが発生 親要素のclickイベントが発生 |
1 |
親要素のclickイベントが発生 |
コンソールに出力されるログにより、clickイベントが発生した要素でイベントハンドラーが呼ばれた後、クリックされた要素の上位の要素でもclickイベントのイベントハンドラーが呼ばれていることが確認できます。
上記のようにイベントが上位の要素に伝播する仕組みをバブリングフェーズと呼ばれます。
本記事でご紹介する.stop修飾子をイベントをバインドする際に指定することで、このバブリングフェーズのイベントの発生を抑制することができます。
v-onディレクティブの.stop修飾子
.stop修飾子は、v-onディレクティブでバインドしたイベントの伝播をキャンセルしますので、v-onディレクティブでバインドするイベントに続けて記載します。
.stop修飾子の書式
.stop修飾子は、v-onディレクティブを使用したイベントのバインド時に以下のように記載します。
1 |
<要素 v-on:イベント名.stop="メソッド(式)"> |
.stop修飾子の動作
.stop修飾子をイベントに対して指定した時の動作は、JavaScriptのEvent.stopPropagation()メソッドを指定した時と同様の動作になります。
.stop修飾子の実装例
ここではv-onディレクティブの.stop修飾子を使用した実装の例(イベントの伝播を抑制する例)を示します。
1 2 3 4 5 6 7 8 9 10 11 |
<div id="app"> <div id="myParent" v-on:click="onClickParent"> 親要素 <div id="myElement" v-on:click="onClickMe"> 自要素 <div id="myChild" v-on:click.stop="onClickChild"> 子要素 </div> </div> </div> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Vue.createApp({ methods: { onClickParent: function(e) { console.log('親要素のclickイベントが発生'); }, onClickMe: function(e) { console.log('自要素のclickイベントが発生'); }, onClickChild: function(e) { console.log('子要素のclickイベントが発生'); }, } }).mount('#app') |
上記の例では、3階層で入れ子になった最下位の要素(子要素)のclickイベントをバインドする際に.stop修飾子を指定しています。
このコードを実行してブラウザーでページを表示し、各要素をクリックしてみると以下の結果がコンソールログに出力されます。
1 2 |
自要素のclickイベントが発生 親要素のclickイベントが発生 |
1 |
子要素のclickイベントが発生 |
1 |
親要素のclickイベントが発生 |
.stop修飾子を指定したidがmyChildのdiv要素(子要素)ではイベントの伝播が行われず、イベントが発生した要素でバインドしたイベントハンドラーのみが実行されているのが確認できます。