はじめに
去年の今頃に僕はVue.jsに出会った。
今日はフロントエンドでは絶対聞いたことある「モーダルウィンドウ」を踏まえて、Vue.jsのおさらいをしていきます。
※参考書:「基礎から学ぶVue.js(通称:猫本)」と「Vue.js入門」は大変わかりやすいので理解が深まりました。
Vue.js文法
モーダルウィンドウで使うであろうVue.jsの文法。
(モーダルウィンドウ以外でももちろん使います。)
transitionタグ
transitionはCSSアニメーションをより簡単に使いやすくする機能。
参考:Enter/Leave とトランジション一覧
<transition>
<div>トランジションさせたい要素</div>
</transition>
上記のタグで設定完了です。
この囲んだ要素がDOMに追加される場合はenter、削除される場合はleaveというクラスがトランジションに追加されます。
フェードインとフェードアウトの中で付与されるトランジションのクラスは6種類です。
v-enter:enterの開始状態。要素が挿入される前に適用され、要素が挿入された 1 フレーム後に削除されます。
v-enter-active:enterの活性状態。トランジションに入るフェーズ中に適用されます。要素が挿入される前に追加され、トランジション/アニメーションが終了すると削除されます。このクラスは、トランジションの開始に対して、期間、遅延、およびイージングカーブを定義するために使用できます。
v-enter-to: バージョン 2.1.8 以降でのみ利用可能です。enterの終了状態です。要素が挿入後 (同時に v-enter が削除されます) 1 フレームが追加されます。トランジション/アニメーションが終了すると削除されます。
v-leave:leaveの開始状態。トランジションの終了がトリガされるとき、直ちに追加され、1フレーム後に削除されます。
v-leave-active:leaveの活性状態。トランジションが終わるフェーズ中に適用されます。leaveトランジションがトリガされるとき、直ちに追加され、トランジション/アニメーションが終了すると削除されます。このクラスは、トランジションの終了に対して、期間、遅延、およびイージングカーブを定義するために使用できます。
v-leave-to: バージョン 2.1.8 以降でのみ利用可能です。leaveの終了状態です。トランジションの終了がトリガされた後 (同時に v-leave が削除されます) 1 フレームが追加されます。トランジション/アニメーションが終了すると削除されます。
slotタグ
スロットタグは親となるコンポーネントから、子となるコンポーネントのテンプレートの一部に差し込む機能のことです。テンプレートの一部の機能を親要素に定義されている機能に差し変わります。
その他
$emit('aaa') ... 親要素のmethods:aaaが呼び出されます。
.self ... event.target要素が自分自身のときにハンドラが呼び出されます。
<div class="modal modal-overlay" @click.self="$emit('close')">
サンプルコード
<template>
<div class="example-modal-window">
<p>modalWindow open</p>
<button @click="openModal">open</button>
<!-- 以下モーダルウィンドウのコンポーネントを定義(ModalWindow.vue) -->
<MyModal v-if="modal" @close="closeModal">
<p>Vue.js Modal Window!!</p>
<div>
<input type="text" v-model="message">
</div>
<!-- footerスロットコンテンツ -->
<template slot="footer">
<button @click="doSend">send</button>
</template>
</MyModal>
</div>
</template>
<script>
import MyModal from 'MyModal.vue'
export default {
components: {
MyModal
},
data() {
return {
modal: false,
message: ''
}
},
methods: {
openModal: () => {
this.modal = true
},
closeModal: () => {
this.modal = false
},
doSend: () => {
if(this.message.length > 0){
alert(this.message)
this.message = ''
this.closeModal()
}else{
alert("message is not valid")
}
}
}
}
</script>
<template>
<!-- ノードの初期描画時にトランジションを適用したい場合はappear -->
<transition name="modal" appear>
<div class="modal modal-overlay" @click.self="$emit('close')">
<div class="modal-window">
<div class="modal-content">
<slot/>
</div>
<footer>
<slot name="footer"><!-- slot="footer"が親要素のコンポーネントに置き換わる -->
<button @click="$emit('close')">Close</button>
</slot>
</footer>
</div>
</div>
</transition>
</template>
<style lang="scss" scoped>
.modal{
&.modal-overlay {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 30;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
}
&-window{
background: #fff;
border-radius: 4px;
overflow: hidden;
}
&-content {
padding: 10px 20px;
}
&-footer {
background: #ccc;
padding: 10px;
text-align: right;
}
}
.modal-enter-active, .modal-leave-active {
transition: opacity 0.4s;
.modal-window {
transition: opacity 0.4s, transform 0.4s;
}
}
.modal-leave-active {
transition: opacity 0.6s ease 0.4s;
}
.modal-enter, .modal-leave-to {
opacity: 0;
.modal-window {
opacity: 0;
transform: translateY(-20px);
}
}
</style>
解説
app.vue
まず、ModalWindowコンポーネントを定義します。
その際にv-if(boolean:modal)を使用してモーダルウィンドウの表示/非表示を制御しています。openをクリックすると、モーダルウィンドウが表示されます。
※template slot=""を使用すると複数の要素をグループ化できます。
ModalWindow.vue
ここではscriptタグはありません。親要素(app.vue)で定義されたmethodsを使って、動的コンテンツを作成します。$emit()を用いて親要素のmethods を呼びます。template slot="footer"の部分がfooterタグに差し変わります。
まとめ
CSSアニメーション機能を使用する場合はトランジションタグ便利ですね。
他にもトランジションタグならではのmethods(BeforeEnter関数)とかも今後紹介していきます。