VueJS 速習チュートリアル

Vue コンポーネント

Vue の コンポーネント(Components) を利用すると、Web ページを管理しやすい小さなパーツに分解できます。

Web ページの他の部分から切り離して、独自のコンテンツや ロジック(Logic) を持つ独立したコンポーネントとして開発を進めることが可能です。モダンな Web ページは、多くの場合、非常に多くの Vue コンポーネントの組み合わせで構成されています。

1. コンポーネントとは何か?

コンポーネントは、ユーザーインターフェースの特定のセクションを カプセル化(Encapsulate) した、再利用可能で自己完結したコードの断片です。これにより、スケーラブルで メンテナンス(Maintenance) が容易な Vue アプリケーションを構築できます。

Vue では、開発者が独自に作成するカスタムコンポーネントのほかに、後ほど学習する <Teleport><KeepAlive> といった組み込みのコンポーネントも存在します。ここでは、自分たちで作成するコンポーネントに焦点を当てていきます。

2. コンポーネントの作成

Vue におけるコンポーネントは、Web ページの拡張性を高め、大規模なプロジェクトのハンドリングを容易にする非常に強力なツールです。
実際にコンポーネントを作成し、プロジェクトに追加してみましょう。

  1. src フォルダ内に新しく components フォルダを作成します。
  2. components フォルダの中に、新しく FoodItem.vue というファイルを作成します。コンポーネント名には、スペースを含まず各単語の頭文字を大文字にする パスカルケース(PascalCase) を用いるのが一般的です。

FoodItem.vue の中身を以下のように記述してください。

FoodItem.vue のコード:

<template>
  <div>
    <h2>{{ name }}</h2>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: 'Apples',
      message: 'I like apples'
    }
  }
};
</script>

<style></style>

この例からわかる通り、コンポーネントもメインの App.vue と同様に、<template><script><style> タグで構成されています。

3. コンポーネントの追加(グローバル登録)

上記のコードにある <script> タグが export default で始まっている点に注目してください。これは、データプロパティを含むオブジェクトを他のファイルで受信(インポート)できることを意味します。これを利用して、main.jsFoodItem.vue をインポートし、プロジェクトに実装します。

まず、元の main.js の最後の行を 2 行に書き換えます。

main.js (書き換え前):

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

次に、FoodItem.vueインポート し、コンポーネントとして登録するために 4 行目と 7 行目を追加します。

main.js (完成形):

import { createApp } from 'vue'
import App from './App.vue'
import FoodItem from './components/FoodItem.vue' // 4行目: インポート

const app = createApp(App)
app.component('food-item', FoodItem) // 7行目: カスタムタグ名を定義して登録
app.mount('#app')

7 行目でコンポーネントが追加されたことで、App.vue 内の <template> タグの中でカスタムタグ <food-item/> として使用できるようになります。

App.vue:

<template>
  <h1>Food</h1>
  <food-item/>
  <food-item/>
  <food-item/>
</template>

<script></script>

<style>
  #app > div {
    border: dashed black 1px;
    display: inline-block;
    margin: 10px;
    padding: 10px;
    background-color: lightgreen;
  }
</style>

開発用サーバーを起動して結果を確認してみてください。複数の FoodItem がレンダリングされているはずです。

4. コンポーネントの個別動作

Vue コンポーネントの非常に強力な特性の一つは、バニラな JavaScript で行うような「ユニークな ID による要素の特定」をせずとも、各コンポーネントが 個別に(Individually) 動作する点です。Vue は各コンポーネントを自動的に独立したものとして扱います。

例として、<div> 要素をクリックしたときにカウントされる機能を実装してみましょう。

まず、App.vue<style> に、ホバー時にポインタを指マークにする CSS を追加して、クリック可能であることを示唆します。

App.vue に追加する CSS:

#app > div:hover {
  cursor: pointer;
}

コンポーネントファイル FoodItem.vue には、データプロパティ clicks、クリックを検知するリスナー、カウントを増やすメソッド、そして表示用の テキスト補間(Text Interpolation) を追加します。

4.1 実装例:独立したカウンタを持つコンポーネント

FoodItem.vue:

<template>
  <div v-on:click="countClicks">
    <h2>{{ name }}</h2>  
    <p>{{ message }}</p>
    <p id="red">クリックされた回数: {{ clicks }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: 'Apples',
      message: 'I like apples',
      clicks: 0
    }
  },
  methods: {
    countClicks() {
      // インスタンス内の clicks をインクリメント
      this.clicks++;
    }
  }
}
</script>

<style>
  #red {
    font-weight: bold;
    color: rgb(144, 12, 12);
  }
</style>