こんにちは、あかしぃです。
Nuxt.jsで、動的コンポーネントを使ったモーダルの実装方法を解説します。Nuxt.jsで、と書いていますが、記述方法はVue.jsでも基本的に同じはずです。
動的コンポーネントとは、「is」属性を使って、コンポーネント内の子コンポーネントを動的に切り替えられるコンポーネントのことです。
言葉ではいまいち伝わりにくいかもしれませんが、Vue公式に例があるので、そちらを参考にしてください。
動的コンポーネントを使えば、「あるページにおいてクリックされる要素(ボタン)ごとに、モーダル内の表示を変える」といったことが簡単にできます。
まず、モーダルを表示させる元のページを作ります。
sample.vue
<template>
<button @click="showModal1">モーダル1を表示</button>
<button @click="showModal2">モーダル2を表示</button>
<modal-wrapper
v-if="showModal"
@close="closeModal">
<component :is="currentModalComponent" />
</modal-wrapper>
</template>
<script>
import ModalWrapper from '@/components/ModalWrapper.vue'
import Modal1 from '@/components/Modal1.vue'
import Modal2 from '@/components/Modal2.vue'
export default {
components: {
ModalWrapper,
Modal1,
Modal2
},
data() {
return {
showModal: false,
currentModalComponent: Modal1
}
},
methods: {
showModal1() {
this.currentModalComponent = Modal1
this.showModal = true
},
showModal2() {
this.currentModalComponent = Modal2
this.showModal = true
},
closeModal() {
this.showModal = false
}
}
}
</script>
※ cssは省略
モーダルは同一デザインのものを使いまわしたいので、ModalWrapperでラップしています。
また、componentのis属性にcurrentModalComponentをバインディングさせています。
これにより、currentModalComponentが変化することで、表示されるモーダルの中身が変化します。
currentModalComponentを更新するのはModal1とModal2メソッドですね。クリックされるボタンによって発火するメソッドが異なるので、自由にcurrentModalComponentを変更することができます。
モーダルの表示/非表示を担うshowModalについてですが、これの管理はvuexに任せてもいいかもしれません。今回は子コンポーネントからのイベント伝達(emit)で更新させることにしています。
次に、ModalWrapperです。
components/ModalWrapper.vue
<template>
<div
class="modal-mask"
@click="closeModal">
<div class="modal-container">
<slot />
</div>
</div>
</template>
<script>
export default {
methods: {
closeModal() {
this.$emit('close')
}
}
}
</script>
<style lang='scss' scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
.modal-container {
width: 90%;
height: 85%;
margin: 15% auto;
padding: 20px 30px;
background-color: white;
text-align: center;
overflow-y: auto;
}
}
</style>
中に子コンポーネントを入れる予定のコンポーネントなので、<slot>タグを用いています。
ModalWrapperの役割は、背景を暗くするといったデザイン面と、子コンポーネントからcloseイベントを伝達することです。
また、背景がクリックされてもモーダルをクローズさせたいので、背景部分にclickイベントを実装しています。
最後に、モーダルの中身となるModal1、Modal2です。
components/Modal1.vue, Modal2.vue
<template>
<div class="modal">
<p>Hello! I'm Modal1(or 2)!</p>
<button @click="closeModal">
</div>
</tempalte>
<script>
export default {
methods: {
closeModal() {
this.$emit('close')
}
}
}
</script>
ボタンのclickイベントで、closeModalメソッドが発火します。そしてcloseイベントが親コンポーネントに伝達され、showModalがfalseになり、モーダルが非表示になるという仕組みです。
今回の用途はモーダルの切り替えでしたが、他にもいろいろ使い道がありそうです。
他にも使えていないVue.jsの機能があるので、それらも積極的に使っていきたいです。
April 06, 2019 - posted by akashixi