その他

【Vue.js】子要素のイベントを親要素に伝播させない方法(バブリング防止方法)

この記事は約4分で読めます。

こんにちは!半澤です!!

仕事上で出会った問題で、子要素をラップする要素がある場合、子要素をクリックすると親要素のクリックイベントも発火してしまう(バブリング)ことがあったので、親要素の発火を阻止しましょう。

対処法

子要素のイベントに.prevent、または.stopを付与する

jsで言うところのpreventDefault(aタグの遷移を防ぐ)とstopPropagation(イベントバブリングを防ぐ)ですね

.stopの挙動を実際に確認してみよ

例:四角で囲った部分をクリックすると「Radio Two」が選択され、選択されたことでセレクトボックスが活性になるフォームを作る

ソースを読み解くと、子要素をラップするチェックボックスのコンポーネントにセレクトボックスを入れた場合、セレクトボックスをクリックすると親要素のコンポーネント(v-container)のクリックイベントも押下されてしまうのを防止するものを作ります

vuetifyを使用していますが、イメージとしてはこんな感じ

<script>
import { Ref ,ref } from 'vue'

// セレクトボックスリスト
const selectBoxList = [
  { id: '1', name: '1番目' },
  { id: '2', name: '2番目' },
  { id: '3', name: '3番目' }
]
// セレクトボックスフォーム
const selectBoxForm = ref(‘')
// チェックボックスフォーム
const checkboxForm: Ref<string[]> = ref([])
</script>

<template>        
  <v-checkbox
    v-model="checkboxForm"
    label="Radio One"
    value="one"
    style="width: 200px"
    @click="console.log('click one radio')"
  />
  <v-container
    style="border: 1px solid #000000"
    @click="() => {
     console.log('click two radio')
     if (checkboxForm.includes('two')) {
      checkboxForm.splice(checkboxForm.indexOf('two'), 1)
     } else {
      checkboxForm.push('two')
     }
   }"
  >
  <v-checkbox
    v-model="checkboxForm"
    label="Radio Two"
    value="two"
    style="width: 200px"
  />
  <v-select
    v-model="selectBoxForm"
    label="Select"
    :items="selectBoxList"
    item-title="name"
    item-value="id"
    :disabled="!checkboxForm.includes('two')"
    style="width: 200px"
    @click<strong>.stop</strong>="console.log('click select box')"
  />
  </v-container>
</template>

キーなのはv-selectタグのclickイベントですね。

.stopが無いと、セレクトボックスをクリックするたびにチェックボックスのオンオフまでクリックイベントが伝播して操作できなくなります

筆末

こんな感じでイベントのプロパティに付与してあげれば防止できます

恥ずかしい話、この現象は認識していましたがバブリングという名称があったのは初耳だったので記事にまとめました。とさ!!

PS.チェックボックスのラベルがRadioになっているのを後から発見しましたが、久しぶりに記事を書いた記念としてこのままにしておきます(﹡ƠωƠ﹡)