Nuxt.js(Vue.js)を使って動的モーダルコンポーネントを実装

今回、動的にモーダル表示するコンポーネントを作りました。「モーダルの状態管理」「親とコンポーネント間のデータの受け渡し」「動的にモーダルの中身を変更する」といった処理が必要で勉強になったので、備忘録代わりに記事にしました。

※ vuexで状態管理を行う実装に変えるとスムーズだと思いました。(別記事で紹介する予定です)

 

【使用するファイル構成】

componets

– modal.vue

pages

– index.vue

 

pages/index.vue側の処理

① 引数付きのイベントを発火

動的にリスト表示している中にある、@click=”openModal(item)”でopenModalイベントと一緒にitemを引数として渡している。

 <ul>
	<li v-for="item in items">
		{{ item.id }}
		{{ item.name }}
		<button @click="openModal(item)">編集</button>
	</li>
</ul>

 

② モーダル表示とコンポーネントへの受け渡し変数にitemを代入

モーダルの状態管理をしているshowModalをtrueに、コンポーネント受け渡し用変数postItemにitemを代入

openModal(item) {
	this.postItem = item;
	this.showModal = true;
}

 

③ madalコンポーネントへのオブジェクトの受け渡し

:valでコンポーネント側にpostItemを渡す。

<modal :val="postItem" v-if="showModal" @close="closeModal"></modal>

 

 

pages/index.vueのソースコード

 

<template>
	<div>
		<ul>
		  <li v-for="item in items">
			{{ item.id }}
			{{ item.name }}
			<button @click="openModal(item)">編集</button>
		  </li>
		</ul>
		<modal :val="postItem" v-if="showModal" @close="closeModal"></modal>
	</div>
</template>
<script>
  import modal from '~/components/modal.vue'
export default {
name: 'app',
components: {
modal
},
data() {
return {
showModal: false,
postItem: '',
items: [
{ id: 1, name: 'aのitem' },
{ id: 2, name: 'bのitem' }
]
}
},
methods: {
openModal(item) {
this.postItem = item;
this.showModal = true;
},
closeModal() {
this.showModal = false;
}
},
}
</script>

 

 

componets/modal.vue側の処理

① 動的に値を所得する

propsで:val=”postItem”から送られてきた値を取得。Objectデータのみを受け取るように定義。

props: {
     // 受け取る属性名を指定
     val: Object // オブジェクトのみ受け取る
}

 

② 動的に値を表示する

valオブジェクトを表示する。

<transition name="modal">
   <div class="modal-mask" @click="$emit('close')">
     <div class="modal-wrapper">
       <div class="modal-container">
             {{ val.id }}
             {{ val.name }}
			<button @click="$emit('close')">
               OK
             </button>
       </div>
     </div>
   </div>
 </transition>

 

③ 親のイベントを発火(モーダルを閉じる)

@click=”$emit(‘close’)”で親にある、@close=”closeModal”を発火させる。(closeModalイベントが発火)

closeModal() {
	this.showModal = false;
}

 

 

componets/modal.vueのソースコード

<template>
  <transition name="modal">
    <div class="modal-mask" @click="$emit('close')">
      <div class="modal-wrapper">
        <div class="modal-container">
              {{ val.id }}
              {{ val.name }}
			  <button @click="$emit('close')">
                OK
              </button>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
  export default {
    name: 'Modal',
    props: {
      // 受け取る属性名を指定
      val: Object // オブジェクトのみ受け取る
    }
  }
</script>

<style scoped>
  .modal-mask {
    position: fixed;
    z-index: 9998;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, .5);
    display: table;
    transition: opacity .3s ease;
  }
  .modal-wrapper {
    display: table-cell;
    vertical-align: middle;
  }
  .modal-container {
    width: 70%;
    margin: 0px auto;
    padding: 20px 30px;
    background-color: #fff;
    border-radius: 2px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
    transition: all .3s ease;
    font-family: Helvetica, Arial, sans-serif;
  }
</style>