Help us understand the problem. What is going on with this article?

vue.jsのcomponentをwebpackで.vueにして単一ファイルコンポーネントにする

More than 1 year has passed since last update.

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を指定すると、scsssassでかける。その時は、scss-loaderが必要になる
// scoped をつけると、そのスタイルはこのファイル内にとどまります。
div {
  text-align: center;
  p {
    color: red;
  }
}
</style>

webpack設定

コンパイルが必要になるのでその件。
ローダーとか
Rails 5.1beta の場合は rails new hogehoge --wabpack=vue ってやれば揃えてくれる。

まとめ

また後で

tkhr
basicinc
マーケティングとテクノロジーで社会のあらゆる問題を解決する集団
https://tech.basicinc.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした