vue.jsのcomponentを .vue
という独立した1つのファイルで管理する方法のまとめです。
vue.js公式のガイドではちらっと出たくらいで、vue-loaderなどのドキュメントを読む必要があります。
Rails5.1beta ではいきなりこの形式のhello worldが入っているので戸惑う方が多かったのではないでしょうか。
僕もその一人です。
コンポーネントと単一ファイルコンポーネントを並べて見比べる形の備忘録的なまとめです。
環境
- vue: 2.2.6
- vue-loader: 11.3.4
- vue-style-loader: 2.0.5
- vue-template-compiler: 2.2.6
- webpack: 2.3.3
当方はjsフレームワークはvue.jsが初めてなのでreactなどとの比較は出てこないです。
componentとは
公式によると
コンポーネントは Vue.js の最も強力な機能の 1 つです。基本的な HTML 要素を拡張して再利用可能なコードのカプセル化を助けます。高いレベルでは、コンポーネントは Vue.js のコンパイラが指定された振舞いを加えるカスタム要素です。場合によっては、特別な is 属性で拡張されたネイティブな HTML 要素の姿をとることもあります。
つらつら書かれていますが、要するに「拡張したHTMLを一塊にして独立させたもの」なイメージ。
パーツ(機能)単位で HTMLをまとめて どこで使っても同じように再利用できるようにする強力な機能。
vue.js本体のMVVMと相まってjQueryでは面倒そうなものをすっきり書けてしかも使いまわせる。やばい。
単一ファイルコンポーネント
基本的には普通のコンポーネントと同じで、パーツ単位でHTMLをまとめられる。
ただし、違うところは、名称の通り、その「パーツを構成するために必要な HTML・CSS・JSをひとまとめ に」して独立した1つのファイルで扱える。
単一ファイルコンポーネントは何が嬉しいのか
ざっくりこんな感じ。
コンポーネント | 単一ファイルコンポーネント | |
---|---|---|
Vueのグローバル汚染 | あり | なし |
シンタックスハイライト | なし | あり |
CSS | 無視される ※ | 有効 |
Javascript制限 | あり ※ | なし |
この表だけだと語弊が生まれる(特に※があるもの)ので公式も見てね。
単一ファイルコンポーネント - Vue.js
特に個人的に嬉しいところは、さっきのこれ
「パーツを構成するために必要な HTML・CSS・JSをひとまとめ に」
これまではHTML・CSS・JSをそれぞれ別のファイルで管理して、id・class、詳細度、グローバル汚染に悩み、悩まされることが多々ありました。
ですが、これがあると、そんな悩みは吹き飛ぶわけですね。
なぜなら、それら全てがコンポーネントの .vue
ファイルの中で閉じられるからですね。
コード比較
単一ファイルコンポーネントをべた褒めしてきましたが、学習するのは面倒です。
見なければならないファイルの数が増えるわけですから。
なので、通常のコンポーネントと比較して単一ファイルコンポーネントを追っていきます。
コンポーネントを使うときはこう
// 登録する
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// root インスタンスを作成する
new Vue({
el: '#example'
})
Vue
オブジェクトに対して my-component
という名前で template
部分のHTMLを登録(作成)する。
メインのインスタンスで vue.js
が対象とするのは #example
。
<div id="example">
<my-component></my-component>
</div>
<script src="./app.js"></script>
HTMLは、 root要素に id="example"
をつける。
その中のコンポーネントを挿入したいところに、呼び出すコンポーネントの名前と同じタグ(のようなもの)を記述する。
そして app.js
を読み込む。
と、結果は次の通り。
<div id="example">
<div>A custom component!</div>
</div>
コンポーネントを Vue
オブジェクトを拡張する形で登録(作成)し、メインのインスタンスを作るとコンポーネントの名前でHTMLが置換される。
単一ファイルコンポーネントを使うときはこう
<!-- 登録する -->
<template>
<div>A custom component!</div>
</template>
.vue
ファイルに <template>
タグを埋め込んでその中にHTMLを書き込む
import MyComponent from './my-component.vue';
// root インスタンスを作成する
new Vue({
el: '#example',
components: { MyComponent },
template: '<my-component></my-component>'
})
ここは変わらず、メインのインスタンスで vue.js
が対象とするのは #example
。
違うのは、 components
で使いたいコンポーネントのオブジェクトを指定して、 template
でコンポーネントと置き換えるタグ(のようなもの)を指定する。
もちろん、 my-component.vue
は読み込む必要がありますので、 import
で読み込みます。
<div id="example">
<my-component></my-component>
</div>
<script src="./app.js"></script>
ここも変わらず、HTMLは、 root要素に id="example"
をつける。
その中のコンポーネントを挿入したいところに、呼び出すコンポーネントの名前と同じタグ(のようなもの) <my-component>
を記述する。
そして app.js
を読み込む。
結果は同じ。
ただし、コンパイルが必要です。
単一ファイルコンポーネントを拡張する
先の例だと、HTMLしか出てきませんでしたが、もちろんJSとCSSも記述できます。
<template>
<div><p v-if="isVisible">{{ message }}</p></div>
</template>
<script>
export default {
data: function() {
return {
message: 'hello'
}
},
computed: {
isVisible: function() {
if (this.message) {
return true;
} else {
return false;
}
}
}
}
</script>
<style lang="scss" scoped>
// langを指定すると、scssやsassでかける。その時は、scss-loaderが必要になる
// scoped をつけると、そのスタイルはこのファイル内にとどまります。
div {
text-align: center;
p {
color: red;
}
}
</style>
webpack設定
コンパイルが必要になるのでその件。
ローダーとか
Rails 5.1beta の場合は rails new hogehoge --wabpack=vue
ってやれば揃えてくれる。
まとめ
また後で