[Vue.js]Propsって何者?という疑問について、モーダルを表示する簡単な例を通して知る方法[Props]

Propsって何者?という疑問について、 モーダルを表示する簡単な例を通して知る方法

Vue.js で Props という名は聞いたものの、いまいち何者なのかわからないという事、あると思います

これまで、Vuetifyに関しての記事の中で、何度も何度も Prop という言葉が出てきたと思いますが、
今回は Vue.js における Prop について、「モーダルウインドウを表示する」という簡単な例をあげながら書いていきたいと思います。

親コンポーネントと子コンポーネント、という概念

WebサイトやWebアプリを構成しているパーツをひもといて分解していくと、
たとえば「タブ型のUI」や「ボタン」「リスト」「モーダルウインドウ」…といった具合に、
個々の「UIパーツ」単位に分けることができますよね。

この、個々のUIパーツの事をさして、コンポーネント( ≒ 部品、構成要素)と、昨今のWeb制作の現場では呼ばれています。
(Vuetifyなどのフレームワークでも、UIパーツを構成する「見た目」も、それが持つ「機能」の部分も含めて「UIコンポーネント」という言葉で呼ばれていますよね。)

コンポーネント単位で制作していく、ということ

とあるWebサイトで、/main/ というページがあったとします。

mainPage.vue という .vue ファイルがそのページ用のコンポーネントだとします。

そのページに「モーダルウインドウを表示させたい」とします。

そうした時、
モーダルウインドウ用のコンポーネントとして
modalWindow.vue という .vue ファイルが別途用意されていれば、
それを mainPage.vue から呼び出せば良い事になります。

簡単な例でいうと、こういう場面で Prop を使うことが出来ます。

この場合、呼び出し元の
mainPage.vue が「親コンポーネント」という概念になり、
呼び出される方の
modalWindow.vue が「子コンポーネント」という扱いになります。

上記のように、親子関係を持つコンポーネント間で
親 → 子
に値を渡す場合に使えるのが、Props
です。

Propsを使ってモーダルを表示させるサンプル

上述した、モーダル用のコンポーネントのサンプルです。
名前は仮に、modalWindow.vue とします。
以下のような .Vueファイルの単一コンポーネントを用意しておきます。

html部分

まずは、template部分。modalの原型をhtmlで記述しておきます。
2行目に v-if="modalShow" とありますが、
これが、親コンポーネントから値を受け取って表示/非表示を切り替えることのできる
Propを指定して、紐付けている部分です。このPropの具体的な内容は、次のjavascript部分で定義します。

<!-- modalWindow.vue -->
<template>
<div class="container-modal" v-if="modalShow">
  <div class="wrapper-modal">
    <h2>やさしいProps</h2>
    <p class="text-modal">
      このように、Vue.js では Prop を使って
      親コンポーネントから値を受け取り、
      要素を表示することができます。
    </p>
  </div>

  <div class="bg-modal"></div>
</div> 
</template>

javascript部分

続いて、javascript部分。5〜12行目までの props: {} が、
文字通りmodal表示用の Prop が定義されている箇所になります。
このように、Props を定義する際は、
type: 真偽値、文字列、数値など、受け取ることのできる値のタイプを指定。この例では、Boolean、つまり真偽値を指定。
default: 最初に持たせておく値。この例では、最初はmodalを非表示にしたいので false を指定。
required: 必須かどうかを指定。

上記のように、この3つを定義しておくことが出来ます。

<!-- modalWindow.vue -->
<script>
export default {
  name: "modalWindow",
  props: {
    modalShow:
    { 
      type: Boolean,
      default: false,
      required: true
    }
  }
};
</script>

style部分

続いて、style部分。
modalというのは、全画面の半透明グレー背景と、
その上に要素を入れることのできる角丸ウインドウがあれば最低限それらしく成立するので、
そんな感じのスタイルを当てています。

<!-- modalWindow.vue -->
<style scoped>
.container-modal {
  height: 100%;
  left: 0;
  position: fixed;
  top: 0;
  width: 100%;
}
.wrapper-modal {
  background: rgba( 255, 255, 255, 1);
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, .3);
  height: 320px;
  left: 50%;
  padding: 40px;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity .3s;
  width: 480px;
  z-index: 20;
}
.bg-modal {
  background: rgba(0, 0, 0, .3);
  height: 100%;
  position: absolute;
  width: 100%;
  z-index: 10;
}
</style>

ここまでが、モーダルウインドウ用のコンポーネント modalWindow.vue になります。

これを、/main/ というページから呼び出してみる方法を、次のセクションから書いていきます。

親コンポーネントから、子コンポーネントの Prop に値を渡してみる

では、/main/ というページ想定の、
親コンポーネントである mainPage.vue から、上記のmodalを呼び出してみます。
具体的には、表示用のボタンを用意して、それを押したらtrueを返して、dataに格納するように @click を指定。
そのdataに格納されたtrueを、先ほどの modalWindow.vue 内の Prop である modalShow に渡してあげる、という流れになります。

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

↑htmlは、単純にこういったボタンがあれば良いです。
次に、 isShow として、真偽値を受け取る data を、親コンポーネント内に定義しておきます。
(もちろん、data名はわかりやすければ何でも良いです)

data: () => ({
  isShow: false
}),
...(中略)...

そして、次のように子コンポーネントに真偽値を渡すわけです。
:modalShow というのが、先ほど modalWindow.vue 内に定義した真偽値を受け取る Prop なので、
このように書いておけば、isShow の値が子コンポーネントである modalWindow.vue に渡り、
モーダルが表示される、という仕組みです。

<modalWindow :modalShow="isShow" />

なぜ親コンポーネント、子コンポーネントに分けるのか

ここまでの記述で
親コンポーネントから子コンポーネントに値を渡して、モーダルウインドウを表示するという事ができるのですが、ただし。
Propとかめんどくさい。そもそも親コンポーネント内にモーダル置いとけば良いんじゃないの?
という疑問が出ると思います。当然そう思うと思います。実際初見だと、すごく理解しづらい部分だと思いますので。

ではなぜ、わざわざモーダルウインドウを modalWindow.vue としてコンポーネント化しているのでしょうか。

それは、この例のように /main/ というページだけからモーダルを呼ぶのならそれでも良いのですが、
こうしてmodalWindow.vue として独立したUIコンポーネント化しておく」ことで、
他のページからも同じようにモーダルを利用することが可能になる
からです。

/main/ というページが全体のメインコンテンツのページだったとして、
その下に
/list/ という一覧ページ、
/detail/ という詳細ページがあったとします。

そのいずれからでも、上述した
親コンポーネント → 子コンポーネント間のPropsを用いることで、
どこでもモーダルを利用することが可能になる、というわけです。
これは、メンテナンス性の面からもメリットがありそうですよね。

このように、「UIパーツをコンポーネント化」して、そのWebサイトなりWebアプリ内で共通利用する概念は、
Vue.js をはじめとしたフロントエンドフレームワークを使ったWeb制作において、
よく使われている方法ですので、覚えておいて損はない概念だと思います。

Vuetifyなどではどうなのか

ここまで読んでいただけば、もうお分かりの方も多いかと思いますが、
当サイトでよくご紹介している「Vuetifyの各種UIコンポーネント」も、
実はこの

「親コンポーネントから → 子コンポーネントを呼び出している」
「親コンポーネント → 子コンポーネント間で値を渡す」

という概念の事をやっている、というわけです。
必要なページに、必要なUIパーツを呼び出して、
それに
props を渡して見た目や挙動を変える
ことが出来ている、
という事になります。

この記事のまとめ

これまでのVue.js関連の記事の中で、
さんざん Props だの Prop だの、書いてきました。
今回は、それらが一体何者で、どんな役割をしているかについて、
親 → 子コンポーネント間で値を渡して、
モーダルウインドウを表示してみる
、というサンプルを使って記事を書いてみました。

今回の続編の記事を書くとしたら、次回は
子 → 親コンポーネント間の値の受け渡しを行う
$emit についても、ふれてみたいと思っています。

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

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