246
226

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のcomponentをwebpackで.vueにして単一ファイルコンポーネントにする

Last updated at Posted at 2017-04-15

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 要素の姿をとることもあります。

コンポーネント - Vue.js

つらつら書かれていますが、要するに「拡張したHTMLを一塊にして独立させたもの」なイメージ。
パーツ(機能)単位で HTMLをまとめて どこで使っても同じように再利用できるようにする強力な機能。
vue.js本体のMVVMと相まってjQueryでは面倒そうなものをすっきり書けてしかも使いまわせる。やばい。 :thumbsup:

単一ファイルコンポーネント

基本的には普通のコンポーネントと同じで、パーツ単位でHTMLをまとめられる。
ただし、違うところは、名称の通り、その「パーツを構成するために必要な HTML・CSS・JSをひとまとめ に」して独立した1つのファイルで扱える。

単一ファイルコンポーネントは何が嬉しいのか

ざっくりこんな感じ。

コンポーネント 単一ファイルコンポーネント
Vueのグローバル汚染 あり なし
シンタックスハイライト なし あり
CSS 無視される ※ 有効
Javascript制限 あり ※ なし

この表だけだと語弊が生まれる(特に※があるもの)ので公式も見てね。
単一ファイルコンポーネント - Vue.js

特に個人的に嬉しいところは、さっきのこれ
「パーツを構成するために必要な HTML・CSS・JSをひとまとめ に」

これまではHTML・CSS・JSをそれぞれ別のファイルで管理して、id・class、詳細度、グローバル汚染に悩み、悩まされることが多々ありました。
ですが、これがあると、そんな悩みは吹き飛ぶわけですね。 :open_hands:
なぜなら、それら全てがコンポーネントの .vue ファイルの中で閉じられるからですね。 :earth_asia:

コード比較

単一ファイルコンポーネントをべた褒めしてきましたが、学習するのは面倒です。
見なければならないファイルの数が増えるわけですから。
なので、通常のコンポーネントと比較して単一ファイルコンポーネントを追っていきます。

コンポーネントを使うときはこう

app.js
// 登録する
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が置換される。

単一ファイルコンポーネントを使うときはこう

my-component.vue
<!-- 登録する -->
<template>
  <div>A custom component!</div>
</template>

.vue ファイルに <template> タグを埋め込んでその中にHTMLを書き込む

app.js
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も記述できます。

my-component.vue
<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 ってやれば揃えてくれる。

まとめ

また後で

246
226
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
246
226

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?