# はじめに

# Vue.js とは?

Vue (発音は /vju:/、view と同様) は、ユーザーインターフェイスを構築するためのプログレッシブフレームワークです。他のモノリシックなフレームワークとは異なり、Vue は少しずつ適用していけるように設計されています。中核となるライブラリはビュー層だけに焦点を当てており、使い始めるのも、他のライブラリや既存のプロジェクトに統合することも容易です。一方で、Vue をモダンなツールサポートライブラリ (opens new window)と組み合わせることで、洗練されたシングルページアプリケーションを開発することもできます。

ここから先に進む前に Vue についてより深く知りたい方のために、基本理念やサンプルプロジェクトについて説明するビデオを作成しました

フロントエンド開発の経験があり、Vue が他のライブラリ/フレームワークとどう違うか知りたい方は、他のフレームワークとの比較を確認してください。

# はじめに

インストール

TIP

公式ガイドは、HTML、CSS そして JavaScript に関する中級レベルの知識を前提としています。フロントエンドの開発が初めてであれば、最初のステップとしてフレームワークに飛び込むのは良いアイデアではないかもしれません。基礎を掴んでから戻ってきましょう!他のフレームワークを使用したことのある経験は役に立ちますが、必須ではありません。

Vue.js を試すには、Hello World の例 (opens new window) が最も簡単です。気軽に別のタブで開いて、基本的な例を試してみましょう。

Vue の他のインストール方法については、インストール ページで紹介しています。注意点として、初心者が vue-cli で始めることは推奨しません(特に Node.js ベースのビルドツールに慣れていない場合)。

# 宣言的レンダリング

Vue.js のコアは、単純なテンプレート構文を使って宣言的にデータを DOM にレンダリングすることを可能にするシステムです:

<div id="counter">
  Counter: {{ counter }}
</div>
1
2
3
const Counter = {
  data() {
    return {
      counter: 0
    }
  }
}

Vue.createApp(Counter).mount('#counter')
1
2
3
4
5
6
7
8
9

これで、初めての Vue アプリケーションが作成できました!一見するとただ文字列をレンダリングするだけのテンプレートですが、Vue は内部で多くの処理をおこなっています。データと DOM は関連付けられ、すべてが リアクティブ(反応的) になっています。どうすればそれが分かるのでしょうか?以下の例で、counter プロパティが 1 秒ごとにインクリメントされたとき、レンダリングされた DOM がどのように変化するかを見てみましょう:








 
 
 



const CounterApp = {
  data() {
    return {
      counter: 0
    }
  },
  mounted() {
    setInterval(() => {
      this.counter++
    }, 1000)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

Counter: 0

文字列の展開に加えて、以下のように要素の属性を束縛(バインディング)することもできます:

<div id="bind-attribute">
  <span v-bind:title="message">
    Hover your mouse over me for a few seconds to see my dynamically bound
    title!
  </span>
</div>
1
2
3
4
5
6
const AttributeBinding = {
  data() {
    return {
      message: 'You loaded this page on ' + new Date().toLocaleString()
    }
  }
}

Vue.createApp(AttributeBinding).mount('#bind-attribute')
1
2
3
4
5
6
7
8
9

See the Pen Attribute dynamic binding by Vue (@Vue) on CodePen.

ここで新しい属性が出てきました。v-bind 属性はディレクティブと呼ばれます。ディレクティブは Vue によって提供された特別な属性であることを示すために v- 接頭辞がついています。これはあなたの推測通り、レンダリングされた DOM に特定のリアクティブな振る舞いを与えます。ここで宣言されているのは、「この要素の title 属性を、現在アクティブなインスタンスにおける message プロパティの最新状態に維持する」ということになります。

# ユーザー入力の制御

ユーザがあなたのアプリケーションと対話できるように、v-on ディレクティブを使ってイベントリスナをアタッチし、インスタンスのメソッドを呼び出すことができます:

<div id="event-handling">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>
1
2
3
4
const EventHandling = {
  data() {
    return {
      message: 'Hello Vue.js!'
    }
  },
  methods: {
    reverseMessage() {
      this.message = this.message
        .split('')
        .reverse()
        .join('')
    }
  }
}

Vue.createApp(EventHandling).mount('#event-handling')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

See the Pen Event handling by Vue (@Vue) on CodePen.

この方法では、DOM を触るのではなくアプリケーションの状態を更新することに注意してください。DOM の操作はすべて Vue によって処理されるので、背後にあるロジックを書くことに集中することができます。

Vue はまた、フォームの入力とアプリケーションの状態を双方向にバインディングするための v-model ディレクティブも提供します:

<div id="two-way-binding">
  <p>{{ message }}</p>
  <input v-model="message" />
</div>
1
2
3
4
const TwoWayBinding = {
  data() {
    return {
      message: 'Hello Vue!'
    }
  }
}

Vue.createApp(TwoWayBinding).mount('#two-way-binding')
1
2
3
4
5
6
7
8
9

See the Pen Two-way binding by Vue (@Vue) on CodePen.

# 条件分岐とループ

要素の有無を切り替えることも非常に簡単です:

<div id="conditional-rendering">
  <span v-if="seen">Now you see me</span>
</div>
1
2
3
const ConditionalRendering = {
  data() {
    return {
      seen: true
    }
  }
}

Vue.createApp(ConditionalRendering).mount('#conditional-rendering')
1
2
3
4
5
6
7
8
9

この例は、テキストや属性だけでなく、DOM の構造にもデータを束縛できることを示しています。さらに Vue には、要素が Vue によって挿入/更新/削除されたとき、自動的にトランジションエフェクト(遷移効果)を適用する強力なトランジションエフェクトシステムも提供します。

以下のサンドボックスで seentrue から false に変更すると、エフェクトを確認することができます:

See the Pen Conditional rendering by Vue (@Vue) on CodePen.

Vue.js には他にもかなりの数のディレクティブがあり、それぞれが特定の機能を持っています。例えば、v-for ディレクティブを使えばアイテムのリストを配列内のデータを使って表示することができます:

<div id="list-rendering">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>
1
2
3
4
5
6
7
const ListRendering = {
  data() {
    return {
      todos: [
        { text: 'Learn JavaScript' },
        { text: 'Learn Vue' },
        { text: 'Build something awesome' }
      ]
    }
  }
}

Vue.createApp(ListRendering).mount('#list-rendering')
1
2
3
4
5
6
7
8
9
10
11
12
13

See the Pen List rendering by Vue (@Vue) on CodePen.

# コンポーネントによる構成

コンポーネントシステムは Vue におけるもうひとつの重要なコンセプトです。それは「小さく、自己完結的で、(多くの場合)再利用可能なコンポーネント」を組み合わせることで、大規模アプリケーションの構築を可能にする概念です。考えてみれば、ほぼすべてのタイプのアプリケーションインターフェイスは、コンポーネントツリーとして抽象化できます。

コンポーネントツリー

Vue において、コンポーネントは本質的にはあらかじめ定義されたオプションを持つインスタンスです。Vue を使ってコンポーネントを登録するのはいたって簡単で、App オブジェクトと同様にコンポーネントオブジェクトを作成し、親の components オプションで定義します:

// Vue アプリケーションを生成する
const app = Vue.createApp(...)

// todo-item という名前の新しいコンポーネントを定義する
app.component('todo-item', {
  template: `<li>This is a todo</li>`
})

// Vue application をマウントする
app.mount(...)
1
2
3
4
5
6
7
8
9
10

これで他のコンポーネントのテンプレートからこのコンポーネントを利用できるようになります:

<ol>
  <!-- todo-item コンポーネントのインスタンスを生成する -->
  <todo-item></todo-item>
</ol>
1
2
3
4

しかし、これでは全ての todo で同じ文字列がレンダリングされてしまうだけで、あまり面白くありません。親のスコープから子コンポーネントへとデータを渡せるようにすべきです。プロパティを受け取れるようにコンポーネントの定義を変えてみましょう:

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})
1
2
3
4

こうすることで、繰り返されるコンポーネントそれぞれに v-bind を使って todo を渡すことができます:

<div id="todo-list-app">
  <ol>
    <!--
      各 todo-item にその内容を表す todo オブジェクトを指定することで、
      内容が動的に変化します。後述する "key" も各コンポーネントに
      指定する必要があります。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id"
    ></todo-item>
  </ol>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const TodoList = {
  data() {
    return {
      groceryList: [
        { id: 0, text: 'Vegetables' },
        { id: 1, text: 'Cheese' },
        { id: 2, text: 'Whatever else humans are supposed to eat' }
      ]
    }
  }
}

const app = Vue.createApp(TodoList)

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})

app.mount('#todo-list-app')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

See the Pen Intro-Components-1 by Vue (@Vue) on CodePen.

このサンプルは不自然ではありますが、アプリケーションをより小さな単位に分割することに成功し、またプロパティのインターフェイスによって子コンポーネントは適切に疎結合な状態になりました。ここからさらに <todo-item> コンポーネントを、より複雑なテンプレートやロジックを使って、親コンポーネントに影響を与えることなく改良することができます。

大規模なアプリケーションでは、開発をおこないやすくするために、アプリケーション全体をコンポーネントに分割することが必要です。コンポーネントについてはガイドの後半でより詳しく述べますが、コンポーネントを使ったアプリケーションのテンプレートがどういうものになるか、(架空の)例をここに載せておきます:

<div id="app">
  <app-nav></app-nav>
  <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
  </app-view>
</div>
1
2
3
4
5
6
7

# カスタム要素との関係

Vue のコンポーネントが Web Components 仕様 (opens new window) の一部である カスタム要素 (Custom Elements) によく似ていることに気付いたかもしれません。これは Vue のコンポーネント構文はその仕様を手本にしているためです。例えば、Vue コンポーネントは Slot API (opens new window)is という特別な属性を実装しています。しかしながら、いくつか重要な違いがあります:

  1. Web Components の仕様は確定しましたが、全てのブラウザにネイティブ実装されているわけではありません。Safari 10.1 以上、Chrome 54 以上、Firefox 63 以上が Web Components をネイティブでサポートしています。一方、Vue コンポーネントは、サポートされる全てのブラウザ(互換ビルドでは IE11 以上)で同じ動作をします。必要があれば、Vue コンポーネントはネイティブなカスタム要素内に含めることもできます。
  1. Vue コンポーネントは、通常のカスタム要素では利用できない重要な機能、中でもクロスコンポーネントデータフロー、カスタムイベント通信やビルドツールとの統合といったものを提供します。

Vue は内部的にはカスタム要素を使っていませんが、カスタム要素として使用または配布する場合に 優れた相互運用性 (opens new window) があります。Vue CLI では、それ自身をネイティブのカスタム要素として登録するような Vue コンポーネントの構築もサポートしています。

# 準備ができましたか?

Vue.js コアの基本的な機能について簡単に紹介しました。このガイドの残りの部分では、基本的な機能だけでなく他の高度な機能についてもっと詳しく扱うので、全てに目を通すようにしてください!

Deployed on Netlify.
最終更新日: 10/8/2020, 11:37:48 PM