【Vue.js】モーダルウィンドウ
実装したいこと
タスク一覧があり、それぞれのタスクタイトルをクリックすると、モーダルウィンドウでタスクの詳細が表示される。
データの流れ
細かいコード内容は省き、大まかな流れだけ追います。
データの流れの説明に必要な部分だけ切り取っているので、インデントぐちゃぐちゃです…
親側
<template> <!-- 必要部分だけ抜粋 --> <!-- ①各タスク名をクリックすると"handleOpenTaskDetailModal(task)"発火 --> <div v-for="task in tasks" :key="task.id" @click="handleOpenTaskDetailModal(task)" > <span>{{ task.title }}</span> </div> <!-- ③親から子に属性としてデータを渡す --> <!-- isVisibleTaskDetailModalをtrue/falseに切り替えることで、子コンポーネントの表示・非表示をv-ifで実現する。--> <transition name="fade"> <!-- ⑨v-on(@に省略可)で子から$emitで渡された'close-modal'を受け取り、メソッド発火 --> <TaskDetailModal :task="taskDetail" v-if="isVisibleTaskDetailModal" @close-modal="handleCloseTaskDetailModal" /> </transition> </template> <script> import TaskDetailModal from '../../components/TaskDetailModal.vue' //2階層上なので、../../となる export default { name: "TaskIndex", components: { TaskDetailModal }, data() { //初期値を設定する(設定しないと警告がでる) return { tasks: [], taskDetail: {}, isVisibleTaskDetailModal: false } }, methods: { // ②各タスククリックで発火される handleOpenTaskDetailModal(task) { this.isVisibleTaskDetailModal = true; // trueにすることで表示 this.taskDetail = task; // ループして引数で受けとったtaskを`taskDetail`に入れる※子側で使う }, // ⑩子から$emitで渡された'close-modal'により発火するメソッド handleCloseTaskDetailModal() { this.isVisibleTaskDetailModal = false; //非表示にするためにfalseにする this.taskDedail= {}; } } } </script>
子側
templateはBootstrapからコピペして少々修正しただけです。
親から属性で渡されたデータをprops
で受け取ります。
このとき、受け取るデータ型を指定します。(指定しないと警告がでる)
<template> <!-- 必要部分だけ抜粋 --> <!-- ⑤親から受け取ったデータtask, descriptionを表示 --> <h5 class="modal-title">{{ task.title }}</h5> <div class="modal-body" v-if="task.description"> <p>{{ task.description }}</p> </div> <div class="modal-footer"> <!-- ⑥閉じるボタンをクリックすると、"handleCloseModal"メソッドが発火する --> <button @click="handleCloseModal" class="btn btn-secondary" data-dismiss="modal">閉じる</button> </div> </template> <script> export default { name: 'TaskDetailModal', props: { // ④親からデータ受け取り task: { title: { type: String, //データ型指定 required: true }, description: { type: String, required: true } } }, methods: { handleCloseModal() { // ⑦閉じるボタンクリックにより発火する。 this.$emit('close-modal') // ⑧$emitで'close-modal'を親側に渡す。 } } } </script> <style scoped> .modal{ display: block; } </style>
データが行ったりきたりして混乱するので、自分で図を書いてみるとわかりやすかったです。