[Vue.js]子→親に値を渡す $emit について、モーダルを操作する簡単な例を通して知る方法[$emit]

子→親コンポーネントに値を渡す $emit について モーダルを操作する簡単な例を通して知る方法

Vue.js で Props を使って開いたモーダルを、今度は $emit をつかって閉じてみる。そんな記事です

この記事は、以下の記事の続編です!ぜひ前回の記事を開きながら、見比べながらご覧になることをオススメします!
[Vue.js]Propsって何者?という疑問について、モーダルを表示する簡単な例を通して知る方法[Props]

この記事は、以前書いた、Vue.js の Prop についての記事の続編です。
前回の記事はこちら → [Vue.js]Propsって何者?という疑問について、モーダルを表示する簡単な例を通して知る方法[Props]
今回は Vue.js における $emit について、「モーダルウインドウをとじる」という簡単な例をあげながら、書いていきたいと思います。

親コンポーネント → 子コンポーネントではPropを使えば良いのがわかった。では、子 → 親の場合は?

前回の記事では、親コンポーネント → 子コンポーネントの流れで値を渡して、
とある値がtrueになったら、モーダルウインドウが開く
という例をご紹介しました。
「モーダルを開く」ボタンを押すとPropにtrueが渡り、モーダルが開く例
↑左上にある「モーダルを表示する」というボタンを押すとPropにtrueが渡って、モーダルウインドウが開く例です。
※詳しいコードは前回の記事参照

ボタン部分は以下のようになっているので、開いたモーダルウインドウを閉じるにはもう一度ボタンを押せば良いわけですね。isShow = !isShow ←このような書き方で、trueの場合はfalseが、falseの場合はtrueが返ります )

<button @click="isShow = !isShow">モーダルを表示する</button>

…が、しかし。先ほどのキャプチャをよく見てください。
「モーダルを開く」ボタンを押すとPropにtrueが渡り、モーダルが開く例
…ん?
モーダル背景に隠れてボタンが…押せ…ない?

なんと、モーダルの半透明の全画面グレー背景があるために、ボタンを押すことが出来なくなってしまいました。何も考えずに前面にモーダルを出してしまうと、こういった事象が起こり得ますよね。

ではどうすればモーダルを閉じられるか。
モーダルをとじる為のボタンをモーダル内に設けた例
↑この様にモーダル内に閉じるボタンを置いておけば、大丈夫と言うことですね。
(※ 他の方法としては、グレーの透明背景部分をクリックしたら閉じる、またはモーダルの右上にcloseアイコンを置いておく方法などが採用できそうです)

ただし、ここで問題が発生します。

前回の記事で書いた通り、このモーダルは
modalWindow.vue としてコンポーネント化しており、
呼び出し元のページの /main/ というページから呼び出している想定です。
(/main/ に対応するコンポーネントを mainPage.vue としている想定です。)

つまり、
親コンポーネント → mainPage.vue
子コンポーネント → modalWindow.vue
という関係性になっています。

Vue.js では、子コンポーネントから → 親コンポーネント内にあるdataの値を直接操作できない(※そのままでは)

<button @click="isShow = !isShow">モーダルを表示する</button>

↑mainPage.vue 内にあるこのボタンが示す通り、このサンプルにおいて、
モーダルの開閉を担っている data は isShow というdataです。

つまり、モーダル内に置いた「モーダルを閉じる」と言うボタンを押した時に
isShow に false を渡してあげればモーダルを閉じることが出来るわけなのですが、

ただモーダル内にボタンを置いただけでは反応してくれません。

Vue.js では、親コンポーネント内に定義されている data を、
子コンポーネントから直接操作することができない
ためです。(これは、その方が意図せぬ上書きが起こりにくくなるので、当然といえば当然の仕様かと思います)

ではどうすればいいのか。

そこで登場するのが、$emit と言うわけです。
$emit を使えば、
子 → 親への値の受け渡しが可能になります。

$emit を使って「子コンポーネント内から → 親コンポーネント」のdataに値を渡して、モーダルを閉じる例

では、$emit の使い方です。まずは、子コンポーネントである modalWindow.vue 内に以下のボタンを置きます。

<!-- modalWindow.vue -->
<button @click="modalClose">モーダルを閉じる</button>

@click は v-on:click の短縮形で、クリックすると modalClose という関数を実行する意味の記述です。modalCloseは、methods内に、以下の様に書いておきます。

<!-- modalWindow.vue -->
methods: {
  modalClose() {
    this.$emit('is-close', false)
  }
}

↑でました。$emit です。これを使うことで、
子 → 親への値の受け渡しができます。
受け取るためには、親側にも追加記述が必要です。

<!-- mainPage.vue -->
<modalWindow :modalShow="isShow" @is-close="isShow = $event" />

↑この様に、mainPage.vue 内で
modalWindow.vue を呼び出しているタグ部分に、
「$emit の値を受け取るよ」という記述を書いておきます。
(末尾の @is-close = $event の部分です)

子コンポーネント modalWindow.vue 内に定義した関数内で、

<!-- modalWindow.vue -->
methods: {
  modalClose() {
    this.$emit('is-close', false)
  }
}

↑この様に
「is-close と言う名前で false を渡すよ」
と定義しているので、親側でも
@is-close = “isShow = $event”
とすれば、
子コンポーネントから送られた値を受け取ることができ、
親コンポーネント内の data である isShow にfalseが渡るためモーダルを閉じる事ができる、
というわけです。

$emit と $eventを使った子 → 親コンポーネント間での値の受け渡しに関するVue.js公式の解説

以下のページに、公式解説があります。
よく読むと、どう言う仕組みなのかわかるかと思います。
コンポーネントの基本 — Vue.js

この記事のまとめ

今回は、前回の記事
[Vue.js]Propsって何者?という疑問について、モーダルを表示する簡単な例を通して知る方法[Props]
の続編として、
子 → 親コンポーネント間で値を渡して、
モーダルウインドウを閉じてみる
、という事について、記事を書いてみました。

子コンポーネントに定義しておき、親コンポーネント(呼び出し元)からの値を受け取る
Props

そして、子コンポーネント(呼び出されている側)内からの変更を親コンポーネントに通知する事ができる
$emit

この2つを理解する事で、
これまで当サイトの複数の記事で書いてきた Vuetify のUIコンポーネントについても、
より理解が深まることかと思います。

それと同時に、
コンポーネント化してUIパーツを使うことによる効率化を知る事で
より一層、
Webサイト上の画面を構成している要素ひとつひとつを
「UIパーツなのだ」と分解して捉える事ができる様になり、
UIそのものに対する理解もきっと深まると思います。

よくよく考えると、Webサイトというのは
「UIパーツの集合体」だと言う事にも、おのずと気がつくはずです。
その個々のUIパーツ上に文字、画像、動画などのコンテンツが乗り、Webサイトとして日頃、我々は閲覧している、ということですね。

当サイトでは、今後もVue.js、Vuetifyを使ったWeb制作に関する記事を書いていきます。

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