1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

モーダルウィンドウから学ぶVue.js

Posted at

はじめに

去年の今頃に僕は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')">

サンプルコード

app.vue
<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>
ModalWindow.vue
<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関数)とかも今後紹介していきます。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?