HTML Importsを使ってモーダルコンポーネントを作る

[VueJS and HTML Imports – Interesting Stuff…](https://johnmj.wordpress.com/2017/06/20/vuejs-and-html-imports/) こちらの記事を参考に、公式で挙げられているモーダルコンポーネントを単一ファイルコンポーネント化してみました

コード一式: https://github.com/satooon/vuejs-tutorial/tree/master/single-file-component

## コード

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <modal v-if="showModal" @close="showModal=false">
        <div slot="header">
            <h3>Modal Header</h3>
        </div>
        <div slot="body">
            Hello World
        </div>
    </modal>

    <button @click="showModal=true">
        showModal
    </button>
</div>
</body>
</html>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<link rel="import" href="./modal-template.html">
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            showModal: false
        }
    });
</script>
```

```modal-template.html
<script type="text/x-template" id="modal-template">
    <transition name="modal">
        <div class="modal-mask">
            <div class="modal-wrapper">
                <div class="modal-container">
                    <div class="modal-header">
                        <slot name="header"></slot>
                    </div>

                    <div class="modal-body">
                        <slot name="body"></slot>
                    </div>

                    <div class="modal-footer">
                        <slot name="footer">
                            <button class="modal-default-button" @click="$emit('close')">close</button>
                        </slot>
                    </div>
                </div>
            </div>
        </div>
    </transition>
</script>

<style type="text/css">
    .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;
        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;
    }

    .modal-header h3 {
        margin-top: 0;
        color: #42b983;
    }

    .modal-body {
        height: 450px;
        overflow-y: scroll;
        margin: 20px 0;
    }

    .modal-default-button {
        float: right;
    }

    .modal-enter {
        opacity: 0;
    }

    .modal-leave-active {
        opacity: 0;
    }

    .modal-enter .modal-container, .modal-leave-active .modal-container {
        -webkit-transform: scale(1.1);
        transform: scale(1.1);
    }
</style>

<script type="text/javascript">
    Vue.component('modal', {
        template: document.currentScript.ownerDocument.querySelector('#modal-template').innerHTML
    });
</script>
```

## 結果

![20180208.gif](https://qiita-image-store.s3.amazonaws.com/0/53200/79b35cbb-8b29-f246-ad62-49b5c74f68da.gif)

Webpack等のビルドツールを使用せずにできるのが利点ですかね