はい、承知いたしました。Vue.jsを初めて学ぶ方向けの、詳細なチュートリアル記事を約5000語で作成します。
Vue.jsチュートリアル完全版:初めてのフレームワーク学習に
はじめに:ようこそ、Vue.jsの世界へ!
Web開発の世界は日々進化しており、よりリッチでインタラクティブなユーザーインターフェース(UI)を効率的に構築するためのツールが求められています。JavaScriptフレームワークは、このような現代のWebアプリケーション開発において不可欠な存在となりました。
数あるJavaScriptフレームワークの中でも、Vue.jsはその学習しやすさ、柔軟性、そしてパフォーマンスのバランスの良さから、世界中で多くの開発者に愛されています。特に、初めてフレームワークを学ぶ方にとって、Vue.jsは非常に優れた選択肢と言えるでしょう。
この記事の目的
この記事は、「プログラミング経験はあるけれど、フレームワークは初めて」「Vue.jsに興味があるけれど、何から始めればいいか分からない」という方を対象に、Vue.jsの基本的な概念から、実践的なアプリケーション構築、そしてさらに踏み込んだ応用トピックまでを網羅的に解説する完全版チュートリアルです。
約5000語というボリュームで、Vue.jsの「なぜ」と「どのように」を丁寧に掘り下げ、読者の皆さんがVue.jsを使った開発の基礎をしっかりと身につけられることを目指します。
さあ、一緒にVue.jsの楽しい旅を始めましょう!
なぜ今、Vue.jsを学ぶのか?
Vue.jsは、他の主要なフレームワーク(ReactやAngularなど)と比較していくつかの明確な利点があります。
- 学習曲線が緩やか: シンプルな設計と分かりやすいドキュメントにより、JavaScriptの基礎知識があれば比較的容易に習得できます。
- 軽量で高速: パフォーマンスが高く、大規模なアプリケーションから小規模な部品まで幅広く利用できます。
- 柔軟性: 既存のプロジェクトに少しずつ導入することも、フルスクラッチでSPA(シングルページアプリケーション)を構築することも可能です。
- エコシステム: 公式が提供するルーター(Vue Router)や状態管理ライブラリ(Pinia/Vuex)など、開発に必要なツールが充実しています。
- 日本語の情報が多い: 日本語の公式ドキュメントも完備されており、日本語での情報検索がしやすいのも大きなメリットです。
これらの理由から、Vue.jsは特に初心者にとって魅力的なフレームワークとなっています。
フレームワークとは何か?ライブラリとの違い
「フレームワーク」と「ライブラリ」という言葉を耳にするかもしれません。これらはどちらもコード開発を助けるツールですが、役割が異なります。
- ライブラリ: 特定の機能を実行するための「部品」や「ツール集」です。開発者が主体となり、必要に応じてライブラリを呼び出して使用します。例えば、jQueryはDOM操作を簡単にするライブラリです。
- フレームワーク: アプリケーション全体の「骨組み」や「枠組み」を提供します。フレームワークが開発の構造を定義し、開発者はその枠組みの中でコードを記述します。フレームワークが処理の流れを制御し、特定のタイミングで開発者のコードを呼び出す、というイメージです。
Vue.jsは、アプリケーションの構造を定義し、データとUIの連携などを管理してくれるため、「フレームワーク」に分類されます。
この記事を通して、Vue.jsがどのようにアプリケーション構築を助けてくれるのかを体験していきましょう。
Vue.jsの基本概念:まずはここから!
Vue.jsを使った開発は、いくつかの重要な基本概念を理解することから始まります。これらはVue.jsの根幹をなす考え方であり、後の複雑な機能もこれらを基盤としています。
1. 宣言的レンダリング (Declarative Rendering)
従来のWeb開発では、JavaScriptを使ってDOM(Document Object Model、Webページの構造を表現するもの)を直接操作し、画面表示を更新することが一般的でした。例えば、ボタンがクリックされたら、その都度JavaScriptで特定のHTML要素を見つけてテキストを変更したり、要素を追加・削除したりします。これは「命令的(Imperative)」なアプローチと呼ばれます。
一方、Vue.jsは「宣言的(Declarative)」なアプローチを採用しています。これは、「データがこうなったら、画面はこう表示されるべき」という「状態(データ)」と「表示(DOM)」の関係を宣言しておくだけで、実際のDOM操作はVue.jsが自動で行ってくれる、という考え方です。
最も簡単な宣言的レンダリングの例が、Mustache構文(二重波括弧 {{ }}
) です。
“`html
“`
この例では、{{ message }}
の部分に、Vueインスタンスの data
オプションで定義した message
プロパティの値が表示されます。もし app.message
の値をJavaScriptで変更すると、{{ message }}
の表示は自動的に更新されます。開発者はDOMを直接操作する必要がありません。これが「宣言的」の強力さです。
v-bind ディレクティブ
HTML要素の属性(id
, class
, href
, src
など)にデータをバインド(関連付け)したい場合は、v-bind
ディレクティブを使用します。
“`html
マウスを乗せてください
“`
v-bind:title="tooltipText"
は、「この <span>
要素の title
属性を、Vueインスタンスの tooltipText
というデータプロパティの値にバインドしてください」という意味になります。tooltipText
の値が変更されると、<span>
要素の title
属性も自動的に更新されます。
v-bind
は非常に頻繁に使用されるため、省略記法としてコロン :
を使うことができます。
html
<span :title="tooltipText">
マウスを乗せてください (省略記法)
</span>
v-html ディレクティブ
要素の内部HTMLとしてデータを表示したい場合は、v-html
ディレクティブを使用します。ただし、ユーザー入力など信頼できないコンテンツに v-html
を使うと、クロスサイトスクリプティング(XSS)攻撃の危険性があるため、注意が必要です。
“`html
“`
2. リアクティブ性 (Reactivity)
Vue.jsの最も強力な機能の一つが「リアクティブ性」です。これは、Vueが管理するデータ(data
オプションで定義されたプロパティなど)が変更されると、そのデータを使用しているDOMの部分が自動的に、かつ効率的に更新される仕組みです。
Vue.jsは、データを監視(リアクティブに)することで、変更を検知し、必要最小限のDOM操作だけで画面を最新の状態に保ちます。開発者はデータの変更に集中でき、DOM操作の複雑さから解放されます。
“`html
{{ count }} 回クリックされました。
“`
この例では、button
がクリックされると increment
メソッドが実行され、this.count
がインクリメントされます。Vue.jsはこの count
の変更を検知し、{{ count }}
を使用している <p>
要素の表示を自動的に 1
, 2
, 3
, … と更新します。開発者はどこでDOMを更新するかを命令する必要はありません。
3. ディレクティブ (Directives)
ディレクティブは、v-
というプレフィックスを持つ特殊な属性です。テンプレート構文の一部であり、HTML要素にVue.jsの特別な振る舞いを適用するために使用されます。
ここまでで v-bind
(または :
) と v-html
を見ましたが、他にも様々なディレクティブがあります。
-
v-if / v-else-if / v-else (条件付きレンダリング): 条件に基づいて要素を完全に表示/非表示(DOMに追加/削除)します。
“`html
ようこそ、{{ username }}さん!
ログインしてください。
“`v-if
がtrue
の場合、その要素とv-else-if
,v-else
のブロックが表示されます。v-if
がfalse
の場合、Vueはその要素をDOMから削除します。条件が頻繁に切り替わる場合は、DOMの追加/削除のコストが発生します。 -
v-show (表示/非表示): 条件に基づいて要素のCSS
display
プロパティを変更することで表示/非表示を切り替えます(要素自体はDOMに残ります)。“`html
このメッセージは表示/非表示が切り替わります。
“`v-show
は、要素のDOM操作が発生しないため、v-if
よりも切り替えコストが低いです。頻繁に表示/非表示が切り替わる要素に使うと効率的です。 -
v-for (リストレンダリング): 配列の要素やオブジェクトのプロパティに基づいて、複数の要素を繰り返し描画します。
“`html
- {{ index }}: {{ item.text }}
“`v-for="(item, index) in items"
は、「items
配列の各要素をitem
という変数で、そのインデックスをindex
という変数で受け取り、繰り返し処理を実行します」という意味です。
:key
属性は非常に重要です!v-for
を使う際は、各要素に一意のキー(この例ではitem.id
)をバインドすることを強く推奨します。Vue.jsは、キーを使用してリストの要素の追加、削除、移動を追跡し、効率的にDOMを更新します。キーがないと、Vue.jsは要素を適切に再利用できず、パフォーマンスの低下や、特定の遷移効果が正しく動作しないなどの問題が発生する可能性があります。特に、リストの要素が変更される可能性がある場合は必須です。 -
v-on (イベントハンドリング): DOMイベント(クリック、マウスオーバー、キー入力など)を監視し、指定したJavaScriptコード(通常はVueインスタンスの
methods
オプションで定義したメソッド)を実行します。“`html
“`v-on
も頻繁に使用されるため、省略記法として@
を使うことができます。html
<button @click="greet">挨拶する (省略記法)</button>イベントには修飾子を付けることもできます。例えば、
:click.prevent
はevent.preventDefault()
を呼び出し、:click.stop
はevent.stopPropagation()
を呼び出します。html
<a href="#" @click.prevent="doSomething">クリックしてもページ遷移しない</a> -
v-model (フォーム入力バインディング): フォーム要素(
<input>
,<textarea>
,<select>
)とVueインスタンスのデータプロパティを双方向でバインドします。これにより、フォーム要素の値が変更されるとデータプロパティも更新され、データプロパティが変更されるとフォーム要素の値も更新されます。“`html
入力されたテキスト: {{ message }}
“`テキストフィールドに何か入力すると、入力内容が即座に
<p>
要素にも反映されることがわかります。v-model
は内部的にはv-bind:value
とv-on:input
(またはv-on:change
など、要素タイプによる) の組み合わせとして機能しています。
これらのディレクティブを組み合わせることで、データの状態に基づいて複雑なUIを効率的に構築できます。
コンポーネント:アプリケーションを部品化する
実際のアプリケーションは、単純な要素の集まりではなく、ヘッダー、サイドバー、記事リスト、コメント欄など、様々な部品から構成されています。これらの部品を再利用可能で独立した単位に分割するのがコンポーネントです。
コンポーネントは、自身のテンプレート(HTML)、スクリプト(JavaScript)、スタイル(CSS)を持つことができます。これにより、アプリケーション全体を理解しやすい小さなブロックに分割し、開発効率と保守性を高めることができます。
なぜコンポーネントが必要か?
- 再利用性: 一度作ったコンポーネントは、アプリケーション内の複数の場所で再利用できます。例えば、ボタンコンポーネント、モーダルコンポーネントなど。
- 保守性: 問題が発生した場合、影響範囲がそのコンポーネント内に限定されるため、原因特定や修正が容易になります。
- 可読性: アプリケーション全体の構造がコンポーネントツリーとして明確になり、コードが読みやすくなります。
- 分割: 大規模なアプリケーションを、複数の開発者が並行して開発しやすくなります。
コンポーネントの定義方法
Vue.jsでコンポーネントを定義するにはいくつかの方法がありますが、現代的な開発ではSingle File Components (SFC)、つまり .vue
ファイルを使用するのが主流です。.vue
ファイルは、<template>
, <script>
, <style>
の3つのブロックで構成されます。
基本的な SFC の例 (MyComponent.vue):
“`vue
{{ title }}
{{ message }}
“`
<template>
: このコンポーネントのHTML構造を記述します。Vueのテンプレート構文(Mustache構文、ディレクティブなど)を使用できます。<script>
: このコンポーネントのJavaScriptロジックを記述します。export default
でコンポーネントオプション(name
,props
,data
,methods
など)を定義します。<style>
: このコンポーネントに適用されるCSSを記述します。scoped
属性を付けると、そのスタイルはこのコンポーネントの要素にのみ適用され、他のコンポーネントに影響を与えません。
コンポーネントの登録と使用
SFC を使用するには、まずビルドツール(Vite や Vue CLI など)が必要です。これらのツールは .vue
ファイルをブラウザが理解できるJavaScript, HTML, CSSに変換します。
SFC を作成したら、他のコンポーネント(またはルートインスタンス)からインポートして使用します。
App.vue (ルートコンポーネントの例):
“`vue
私のアプリケーション
最後にカウンターが更新された値: {{ lastCounterValue }}
“`
この例では、App.vue
がルートコンポーネントとして機能し、MyComponent.vue
をインポートして <MyComponent />
のタグで使用しています。このように、親コンポーネントのテンプレート内で子コンポーネントを使用することを「コンポーネントのネスト」と呼びます。
Props:親から子へのデータ受け渡し
親コンポーネントから子コンポーネントへデータを渡すには、Props (プロパティ) を使用します。子コンポーネントは、props
オプションで受け取るプロパティを宣言します。親コンポーネントは、子コンポーネントを使用する際に属性のように値を渡します。
上記の MyComponent.vue
では、title
と initialCounter
を props として宣言しています。App.vue
では、<MyComponent title="最初のコンポーネント" :initial-counter="10" />
のように属性として値を渡しています。:initial-counter="10"
のように :
を使うのは v-bind
の省略記法で、JavaScriptの式(数値の 10
)をバインドしていることを意味します。:title="'最初のコンポーネント'"
のように文字列リテラルもバインドできますが、静的な文字列の場合は :
なしで <MyComponent title="最初のコンポーネント" />
と書いても同じ意味になります。
子コンポーネント内で受け取った props は、data
や methods
と同様に this.propName
でアクセスできます。ただし、子コンポーネント内で props の値を直接変更してはいけません。これは「一方向データフロー」の原則であり、データの流れを追跡しやすくするために重要です。子コンポーネントが親に何か変更を伝えたい場合は、後述のイベントを使用します。
Custom Events:子から親へのイベント通知
子コンポーネントが親コンポーネントに何か(例えば、ユーザーの操作やコンポーネントの状態変化など)を伝えたい場合は、Custom Events を使用します。子コンポーネントは $emit
メソッドを使って任意の名前のイベントを発行し、親コンポーネントはそのイベントを @eventName
のようにリスニングします。
上記の MyComponent.vue
では、incrementCounter
メソッド内で this.$emit('counter-updated', this.counter);
としています。これは、「counter-updated
という名前のイベントを発行し、現在の counter
の値を引数として渡します」という意味です。
App.vue
では、子コンポーネントを使用する箇所で @counter-updated="handleCounterUpdate"
としています。これは、「MyComponent
から counter-updated
イベントが発生したら、親コンポーネントの handleCounterUpdate
メソッドを実行してください」という意味です。イベントと一緒に渡された引数(この場合は this.counter
の値)は、handleCounterUpdate
メソッドの引数として渡されます。
Props と Events を組み合わせることで、親子のコンポーネント間でデータをやり取りし、アプリケーションの機能を構築していきます。この「Props Down, Events Up」の考え方は、Vue.jsを含む多くのコンポーネントベースのフレームワークで共通のパターンです。
Slot:コンテンツの配布
コンポーネントのテンプレート内で、親コンポーネントから渡されたコンテンツを配置したい場合があります。例えば、汎用的なモーダルコンポーネントがあって、そのモーダルの中身だけを親コンポーネントで指定したい、といったケースです。このような場合に使用するのがSlot(スロット)です。
子コンポーネントのテンプレート内の <slot></slot>
タグは、親コンポーネントがその子コンポーネントのタグ内に記述したコンテンツの「プレースホルダー」として機能します。
Modal.vue (子コンポーネントの例):
“`vue
“`
App.vue (親コンポーネントでの使用例):
“`vue
カスタムヘッダータイトル
これはモーダルの**メインコンテンツ**です。
自由にHTML要素を配置できます。
“`
- デフォルトスロット:
<slot></slot>
と名前を指定しないスロットです。親コンポーネントの子タグ内に直接記述されたコンテンツがここに入ります。 - 名前付きスロット:
<slot name="slotName"></slot>
のように名前を指定したスロットです。親コンポーネント側では<template v-slot:slotName>...</template>
(または省略記法の#slotName
) を使って対応するスロットにコンテンツを配置します。 - スロットタグ内に記述したコンテンツ(例:
<h3>デフォルトヘッダー</h3>
)は、親コンポーネントから対応するスロットにコンテンツが提供されなかった場合の「フォールバックコンテンツ」として表示されます。
コンポーネント、Props、Events、Slotは、Vue.jsでアプリケーションを構築する上での基本かつ非常に強力な概念です。これらを理解し活用することで、保守しやすく再利用性の高いコードを書くことができるようになります。
実例プロジェクト:ToDoリストを作ってみよう!
ここからは、これまでに学んだVue.jsの基本概念とコンポーネントの知識を使って、実際にToDoリストアプリケーションを構築してみましょう。手を動かすことで、理解が深まります。
プロジェクトの要件定義
作成するToDoリストアプリケーションは、以下の機能を持ちます。
- ToDo項目をテキスト入力で追加できる。
- 追加されたToDo項目がリスト表示される。
- 各ToDo項目には、完了/未完了を示すチェックボックスがある。
- チェックボックスを操作すると、ToDo項目の状態(完了/未完了)が切り替わる。
- 各ToDo項目を削除できるボタンがある。
- 全てのToDo、未完了のToDo、完了済みのToDoでリストをフィルタリングできる。
プロジェクトのセットアップ:Vite を使おう
現代のVue.js開発では、高速なビルドツールである Vite を使うのが一般的です。Vite を使ってVue.jsプロジェクトを作成しましょう。Node.js がインストールされている必要があります。
ターミナルを開き、以下のコマンドを実行します。
bash
npm create vue@latest
このコマンドを実行すると、いくつかの質問が表示されます。初めての場合は、基本的にEnterキーを押してデフォルトの選択肢を選んでいけば問題ありません。(例えば TypeScript は No
、ESLint は No
など)
“`
✔ Project name: » vue-todo-app
✔ Add TypeScript? » No
✔ Add JSX Support? » No
✔ Add Vue Router for Single Page Application development? » No
✔ Add Pinia for State Management? » No
✔ Add Vitest for Unit Testing? » No
✔ Add Cypress for End-to-End Testing? » No
✔ Add ESLint for Code Quality? » No
✔ Add Prettier for Code Formatting? » No
Scaffolding project in /path/to/your/directory/vue-todo-app…
Done. Now run:
cd vue-todo-app
npm install
npm run dev
“`
プロジェクトが作成されたら、指示通りにディレクトリに移動し、依存関係をインストールして開発サーバーを起動します。
bash
cd vue-todo-app
npm install
npm run dev
開発サーバーが起動すると、ローカル環境でアプリケーションが閲覧できるURL(通常は http://localhost:5173/
など)が表示されます。ブラウザでアクセスしてみましょう。Vueのロゴが表示されたデフォルトの画面が見えるはずです。
プロジェクトのディレクトリ構成は以下のようになります。(不要なファイルは削除されているかもしれません)
vue-todo-app/
├── index.html
├── package.json
├── vite.config.js
└── src/
├── main.js # アプリケーションのエントリーポイント
├── App.vue # ルートコンポーネント
└── style.css # グローバルスタイル
src/App.vue
がアプリケーションのルートコンポーネントです。このファイルを編集してToDoリストを作成していきます。デフォルトのコードは全て削除して、シンプルな状態から始めましょう。
src/App.vue の初期状態:
“`vue
“`
1. ToDo項目の追加機能
まず、ToDoを入力するフォームと、追加されたToDoを保持するデータを作成します。
src/App.vue:
“`vue
ToDoリスト
“`
解説:
data()
にnewTodoText
とtodos
というリアクティブなデータを定義しました。<input>
要素にv-model="newTodoText"
を使い、入力内容とnewTodoText
を双方向バインドしています。<input>
に@keyup.enter="addTodo"
を付けることで、Enterキーが押されたときにもaddTodo
メソッドが実行されるようにしています。<button>
に@click="addTodo"
を付け、クリックでaddTodo
メソッドを実行します。addTodo
メソッド内で、新しいToDoオブジェクトを作成し、this.todos
配列にpush
しています。Vueは配列の変更を検知し、後でリスト表示を自動更新します。- 入力後に
this.newTodoText = '';
で入力フォームをクリアしています。
ブラウザで確認すると、入力欄にテキストを入れて「追加」ボタンを押すかEnterキーを押しても、まだリスト表示はされませんが、内部的には todos
配列にデータが追加されています。
2. ToDoリスト表示 (v-for の活用)
次に、todos
配列の中身をリストとして表示します。ここでは v-for
ディレクティブを使用します。
src/App.vue (テンプレート部分):
“`vue
ToDoリスト
-
{{ todo.text }}
“`
解説:
<ul>
要素の中に<li v-for="todo in todos" :key="todo.id">
を追加しました。v-for="todo in todos"
は、todos
配列の各要素に対して繰り返し処理を行い、現在の要素をtodo
という変数に格納します。:key="todo.id"
で、各ToDo項目に一意のid
をキーとして指定しています。これはv-for
を使う上で重要です。{{ todo.text }}
で、各ToDoオブジェクトのtext
プロパティを表示しています。
これで、ToDoを追加するたびにリストに項目が表示されるようになったはずです。
3. ToDo項目の詳細表示と完了/未完了切り替え
各ToDo項目にチェックボックスを追加し、完了状態を切り替えられるようにします。
src/App.vue (テンプレート部分):
“`vue
ToDoリスト
-
{{ todo.text }}
“`
解説:
<li>
要素の中に<input type="checkbox" v-model="todo.completed">
を追加しました。- チェックボックスの
v-model
をtodo.completed
にバインドすることで、チェックボックスの状態とToDoオブジェクトのcompleted
プロパティが双方向で同期します。チェックボックスをオンにするとtodo.completed
がtrue
に、オフにするとfalse
になります。メソッドを書かずに状態を切り替えられるのがv-model
の便利な点です。
- チェックボックスの
<li>
要素に:class="{ completed: todo.completed }"
を追加しました。:class
はv-bind:class
の省略記法です。これは、todo.completed
がtrue
の場合に、<li>
要素にcompleted
というCSSクラスを適用することを意味します。これにより、CSSで完了したToDoにスタイルを適用できます。
- スタイルに
.completed span
のルールを追加し、完了したToDoのテキストに打ち消し線が表示されるようにしました。
これで、チェックボックスのオン/オフでToDo項目の見た目が変わるようになったはずです。
4. ToDo項目の削除機能
各ToDo項目に削除ボタンを追加し、クリックでその項目を削除できるようにします。
src/App.vue (テンプレート部分):
“`vue
ToDoリスト
-
{{ todo.text }}
“`
解説:
- 各
<li>
要素に<button class="delete-button" @click="removeTodo(todo.id)">削除</button>
を追加しました。 - ボタンのクリックイベントで
removeTodo
メソッドを呼び出し、引数として現在のtodo
のid
を渡しています。 removeTodo(todoIdToRemove)
メソッドでは、配列のfilter
メソッドを使って、引数で受け取ったtodoIdToRemove
とid
が異なるToDoだけを残すことで、該当のToDoを削除しています。this.todos = ...
とすることで、todos
配列自体を新しい配列で置き換えています。Vueはこれを検知し、DOMを更新します。
これで、各ToDo項目の横に削除ボタンが表示され、クリックで削除できるようになりました。
5. ToDoリストのフィルター機能
「全て」「未完了」「完了済み」でリストをフィルタリングする機能を追加します。これは、リスト表示に算出プロパティ (Computed Properties) を使うのに最適な例です。
src/App.vue (テンプレート部分):
“`vue
ToDoリスト
-
{{ todo.text }}
“`
解説:
data()
にfilter
というデータプロパティを追加し、初期値を'all'
としました。- フィルター用の3つのボタンを追加しました。各ボタンには
@click="filter = '...'"
を付けて、クリックされたボタンに応じてfilter
の値を更新するようにしています。 :class="{ active: filter === '...' }"
を使い、現在のfilter
の値に対応するボタンにactive
クラスを適用し、スタイルで区別できるようにしています。- 新しく
computed
オプションを追加し、その中にfilteredTodos
という算出プロパティを定義しました。filteredTodos
はthis.filter
またはthis.todos
が変更されると自動的に再計算されます。switch (this.filter)
文を使って、現在のfilter
の値に応じてthis.todos
配列をフィルタリングした結果を返しています。
<ul>
のv-for
をv-for="todo in filteredTodos"
に変更しました。これにより、表示されるリストがfilter
の状態に応じて自動的に切り替わるようになります。
ブラウザで確認し、ToDoを追加したり、完了状態を切り替えたり、フィルターボタンをクリックしたりして、動作を確認してみましょう。データ(todos
と filter
)が変更されるたびに、画面表示(リスト)が自動的に更新されることを体験できます。これがVue.jsのリアクティブ性の力です。
6. コンポーネントへの分割 (ToDoItem コンポーネント)
現在のコードは App.vue
一つに全てのロジックが集約されています。ToDoリストアプリケーションの場合、各ToDo項目(チェックボックス、テキスト、削除ボタン)は独立した一つの部品と考えることができます。これをコンポーネントに分割することで、コードの整理と再利用性を高めることができます。
src/components
ディレクトリを作成し、その中に TodoItem.vue
ファイルを作成しましょう。
src/components/TodoItem.vue:
“`vue
{{ todo.text }}
“`
次に、App.vue
を修正して、作成した TodoItem
コンポーネントを使用するようにします。
src/App.vue:
“`vue
ToDoリスト
@remove=”removeTodo”
/>
“`
解説:
TodoItem.vue
を作成し、各ToDo項目に関するテンプレート、スクリプト、スタイルをそこに移動しました。TodoItem
はtodo
オブジェクトを親からprops
として受け取るように定義しました。- 削除ボタンのクリック時、
$emit('remove', todoId)
を使って親コンポーネントにremove
イベントと削除対象のIDを通知するようにしました。 App.vue
でTodoItem.vue
をインポートし、components
オプションに登録しました。v-for
の中で<TodoItem>
タグを使用し、:todo="todo"
で現在のToDoオブジェクトをTodoItem
のtodo
prop に渡しています。@remove="removeTodo"
で、TodoItem
から発行されたremove
イベントをApp.vue
のremoveTodo
メソッドで受け取るようにしています。
これにより、コードがより整理され、TodoItem
は独立した部品として再利用可能になりました。アプリケーションの見た目や動作は分割前と変わりませんが、内部構造が改善されました。
(Optional) データ永続化:ローカルストレージ
アプリケーションをリロードしてもデータが消えないように、ブラウザのローカルストレージにToDoリストを保存/読み込みする機能を追加してみましょう。これは、Vueのライフサイクルフックを使う良い例です。
src/App.vue (Script部分に追記):
“`vue
“`
解説:
STORAGE_KEY
という定数でローカルストレージのキーを定義しました。data()
のtodos
の初期化時に、localStorage.getItem(STORAGE_KEY)
でローカルストレージからデータを読み込み、JSON.parse()
でJavaScriptオブジェクトに戻しています。もしデータがなければ'[]'
をパースして空の配列として初期化します。addTodo
とremoveTodo
メソッドの最後にthis.saveTodos()
を呼び出すようにしました。- 新しく
saveTodos
メソッドを追加し、this.todos
配列をJSON.stringify()
で文字列化してローカルストレージに保存するようにしました。 - ウォッチャ (
watch
) を使用して、todos
配列の変更を監視するようにしました。handler
関数の中でsaveTodos
を呼び出します。deep: true
オプションにより、todos
配列自体の変更だけでなく、配列内のToDoオブジェクトのプロパティ(completed
など)の変更も検知してhandler
が実行されるようになります。これで、チェックボックスのオン/オフだけでも自動保存されます。
これにより、ToDoリストアプリケーションを閉じても、次回開いたときに以前の状態が復元されるようになりました。
このToDoリストプロジェクトを通して、Vue.jsの基本的なデータバインディング、ディレクティブ、コンポーネントの概念を実践的に学ぶことができました。
さらに深く学ぶ:Vue.jsの強力な機能
ToDoリストの構築でVue.jsの基本を掴んだところで、さらにアプリケーション開発に役立ついくつかの強力な機能を見ていきましょう。
算出プロパティ (Computed Properties)
先ほどのToDoリストのフィルター機能で computed
オプションを使用しました。算出プロパティは、依存するデータに基づいて動的に値を生成し、その結果をキャッシュする機能です。
- 依存関係追跡: 算出プロパティ内で使用されているデータプロパティ(この例では
this.todos
とthis.filter
)が変更されると、算出プロパティは自動的に再評価されます。 - キャッシング: 依存データが変更されない限り、同じ算出プロパティに複数回アクセスしても、関数は再実行されず、キャッシュされた以前の結果が返されます。これは、特に計算コストが高い処理の場合にパフォーマンスを向上させます。
算出プロパティは、テンプレート内で複雑な式を書く代わりに使うことで、テンプレートを読みやすくする効果もあります。
例えば、「未完了のToDoの数」を表示したい場合、算出プロパティを使うことができます。
“`vue
未完了のToDo: {{ remainingTodosCount }} 件
“`
remainingTodosCount
は this.todos
配列に依存しているため、todos
が変更されるたびに自動的に再計算され、表示も更新されます。
ウォッチャ (Watchers)
ウォッチャは、特定のデータプロパティの変更を「監視」し、変更が発生した際に指定された関数を実行する機能です。算出プロパティとは異なり、値を返すのではなく、副作用(非同期処理、DOM操作など)を実行したい場合に適しています。
ToDoリストのローカルストレージ保存で、todos
の変更を監視するためにウォッチャを使用しました。
javascript
watch: {
todos: {
handler(newTodos, oldTodos) {
console.log('todos が変更されました!');
// 例:APIにデータを送信する、ログを記録するなど
this.saveTodos(); // ローカルストレージ保存という副作用を実行
},
deep: true // 配列やオブジェクトの内部変更も監視
// immediate: true // コンポーネント作成時に即座に handler を一度実行したい場合
}
}
handler
関数は、新しい値と古い値の2つの引数を受け取ります。ウォッチャは、特定のデータの変更に応じて何かをするという目的に使われます。
ライフサイクルフック (Lifecycle Hooks)
Vueコンポーネントは、その生成から破棄されるまでの間に特定の段階を経ます。これらの段階で実行される関数を定義できるのが「ライフサイクルフック」です。
主なライフサイクルフック:
beforeCreate
: インスタンスが初期化される直前。データやイベントはまだ設定されていない。created
: インスタンスが作成された後。データやイベントが設定され、リアクティブになった後。テンプレートはまだDOMにマウントされていない。非同期処理(API呼び出しなど)はこのフックで行うのが一般的。beforeMount
: テンプレートがDOMにマウントされる直前。mounted
: テンプレートがDOMにマウントされた後。DOM要素にアクセスできる。外部ライブラリの初期化など、DOM操作が必要な処理はこのフックで行うのが一般的。beforeUpdate
: データが変更され、DOMが更新される直前。updated
: データ変更によりDOMが更新された後。beforeUnmount
: コンポーネントがアンマウントされる直前。イベントリスナーの削除など、クリーンアップ処理を行うのに適している。unmounted
: コンポーネントがDOMからアンマウントされた後。
ToDoリストの例で、ローカルストレージからの読み込みを data()
の初期化で行いましたが、created
フックで行うこともできます。
javascript
export default {
// ... data, computed, methods, watch ...
created() {
// コンポーネントが作成された後にローカルストレージから読み込む
console.log('created フックが呼ばれました。');
this.todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
},
mounted() {
// コンポーネントがDOMにマウントされた後に何かしたい場合
console.log('mounted フックが呼ばれました。');
}
// ... other hooks ...
}
ライフサイクルフックを理解することで、コンポーネントの特定のタイミングで適切な処理を実行できるようになります。
Router (Vue Router)
シングルページアプリケーション(SPA)では、ページ遷移してもブラウザのフルリロードは発生せず、JavaScriptによって画面の一部が書き換えられます。このようなクライアントサイドでのルーティングを管理するための公式ライブラリが Vue Router です。
Vue Router を使うと、URLパスとVueコンポーネントをマッピングし、ナビゲーション(リンククリックなど)に応じて適切なコンポーネントを表示することができます。
ToDoリストのような単純なアプリケーションでは不要かもしれませんが、複数のページ(例: トップページ、ToDo一覧、設定ページなど)を持つアプリケーションを構築する際には不可欠です。
状態管理 (State Management – Pinia)
アプリケーションの規模が大きくなり、複数のコンポーネント間でデータを共有したり、複雑なデータの流れを管理したりする必要が出てくると、PropsやEventsだけでは辛くなってきます。このような場合に役立つのが「状態管理パターン」およびライブラリです。
Vue.jsの公式推奨状態管理ライブラリは Pinia (Vue 3向け) です。Pinia を使うと、アプリケーション全体で共有される「状態(state)」を一箇所に集中管理できます。どのコンポーネントからでもその状態にアクセスしたり、変更したりできるようになります。
ToDoリストの例で言えば、もしToDoリストデータが複数の独立したコンポーネント(例えば、リスト表示コンポーネント、完了済みアイテム数表示コンポーネント、入力フォームコンポーネントなど)で共有される場合、Pinia を導入すると管理が楽になります。
Composition API (Setup 関数)
Vue 3 で導入された Composition API は、コンポーネントロジックをより柔軟かつ再利用可能な形で記述するための新しいスタイルのAPIです。Options API (data, methods, computed, watch などのオプションをオブジェクトで記述するこれまでのスタイル) とは異なります。
Composition API は、setup()
関数の中でリアクティブな状態 (ref
, reactive
)、算出プロパティ (computed
)、ウォッチャ (watch
) などを定義し、それらをまとめて返します。これにより、特定の機能(例: 位置情報を取得する機能、フォーム入力のバリデーション機能など)に関連するロジックをまとめて記述し、他のコンポーネントで簡単に再利用(Composable と呼ばれるカスタムフックとして抽出)できるようになります。
ToDoリストの例を Composition API で書き直すと以下のようになります。(App.vue の <script>
部分のみ)
“`vue
ToDoリスト
```
Composition API は初学者には Options API より少し難しく感じるかもしれませんが、より複雑なアプリケーションを開発する際にはその利便性を実感できるはずです。Vue 3 からは Composition API が主流になってきています。
開発ツール (Vue Devtools)
Vue.jsアプリケーションの開発には、ブラウザ拡張機能である Vue Devtools が非常に役立ちます。これを使うと、Vueコンポーネントのツリー構造、各コンポーネントのデータ (data, props, computed)、イベント、Vuex/Pinia ストアの状態などをリアルタイムに確認・操作できます。デバッグ作業において非常に強力なツールです。
Chrome または Firefox の拡張機能ストアからインストールできます。
開発環境のセットアップ詳細
Viteを使ったプロジェクト作成は既に体験しましたが、ここでは開発環境についてもう少し詳しく触れておきます。
Node.js と npm/yarn/pnpm
Vue.jsを含む多くのフロントエンド開発はNode.js環境上で行われます。まだインストールしていない場合は、公式サイトから最新版をインストールしてください。Node.jsをインストールすると、パッケージマネージャーである npm (Node Package Manager) も一緒にインストールされます。
npm 以外にも、yarn や pnpm といったパッケージマネージャーがあります。これらは npm と同様に、ライブラリのインストールや管理を行います。どのマネージャーを使っても大きな問題はありませんが、プロジェクト内で統一することが重要です。npm create vue@latest
コマンドも、内部的にはこれらのパッケージマネージャーを使用しています。
Vite を使用したプロジェクト作成 (create-vue
)
先ほど使用した npm create vue@latest
コマンドは、Vueプロジェクトを素早く始めるための公式推奨の方法です。内部的には Vite を使用してプロジェクトを構築します。
生成される主なディレクトリやファイルの意味は以下の通りです。
index.html
: アプリケーションのエントリーポイントとなるHTMLファイルです。Viteによってビルド時に注入されるスクリプトタグによってVueアプリケーションが読み込まれます。package.json
: プロジェクトの情報(名前、バージョンなど)と依存関係(インストールされているライブラリとそのバージョン)、そして実行可能なスクリプト(dev
,build
,preview
など)が記述されています。vite.config.js
: Viteのビルド設定ファイルです。必要に応じて、プラグインの追加やビルドオプションの変更などを行います。src/
: アプリケーションのソースコードを配置するディレクトリです。main.js
: Vueアプリケーションインスタンスを作成し、DOMにマウントするエントリーポイントファイルです。ここでルートコンポーネント (App.vue
) を読み込み、アプリケーション全体の設定(ルーター、ストアなど)を行います。App.vue
: アプリケーションのルートコンポーネントです。他のコンポーネントを配置する起点となります。components/
: 再利用可能な子コンポーネントを配置するディレクトリです。assets/
: 画像やフォントなどの静的リソースを配置するディレクトリです。views/
(またはpages/
): Vue Router を使う場合に、各ページに対応するコンポーネントを配置するディレクトリです。(create-vue
で Router を追加した場合に生成されます)
VS Code と役立つ拡張機能
多くのVue.js開発者は、Microsoftが提供する無料のエディタである VS Code を使用しています。VS Code に以下の拡張機能をインストールすると、開発効率が大幅に向上します。
- Volar: Vue 3 のための公式推奨拡張機能です。
.vue
ファイルのシンタックスハイライト、コード補完、型チェック、エラーチェックなどを提供します。以前は Vue 2 向けの Vetur がよく使われていましたが、Vue 3 では Volar が推奨です。 - ESLint: JavaScript/Vueコードの構文エラーやスタイル違反をチェックし、コード品質を向上させるためのツールです。
- Prettier: コードを自動的にフォーマットし、チーム内でのコーディングスタイルを統一するのに役立ちます。
これらのツールは、Viteプロジェクト作成時にオプションで追加することもできますが、手動で設定することも可能です。
まとめ:Vue.js学習の次のステップ
ここまで、Vue.jsの基本的な概念から始め、コンポーネントを使ったアプリケーション構築、そしてToDoリストの実践的な開発を通して、Vue.jsの強力さと開発の楽しさを体験してきました。
学習の振り返り
この記事で学んだ主要なポイントを振り返ってみましょう。
- Vue.jsは宣言的なUI構築を得意とするフレームワークであること。
{{ }}
、v-bind
、v-on
、v-if
、v-for
、v-model
といったディレクティブの基本的な使い方。- データとUIが自動的に同期するリアクティブ性の仕組み。
- コンポーネントによるアプリケーションの部品化と、Props、Events、Slotによるコンポーネント間連携の重要性。
- 算出プロパティ、ウォッチャ、ライフサイクルフックといった、より高度な機能の用途。
- Viteを使ったモダンなVue.js開発環境のセットアップ方法。
- Composition API による新しい記述スタイル。
これらはVue.js開発の基礎となる要素です。これらの概念をしっかりと理解できたなら、もうあなたはVue.jsの世界に一歩踏み出せています。
次のステップ
このチュートリアルで得た知識を元に、さらに学習を進めるためのいくつかのステップを提案します。
- 公式ドキュメントを熟読する: Vue.jsの公式ドキュメントは非常に質が高く、詳細かつ分かりやすいです。この記事でカバーしきれなかった機能や、各機能のより深い解説、APIリファレンスなどが豊富にあります。困ったときやさらに学びたいときは、まず公式ドキュメントを参照しましょう。
- ToDoリストを拡張する: 作成したToDoリストに新しい機能を追加してみましょう。例えば、ToDoの編集機能、並べ替え機能、完了済みToDoの一括削除、カテゴリー分けなど、様々な機能が考えられます。新しい機能を実装する過程で、学んだ概念をより深く理解できます。
- 新しいプロジェクトに挑戦する: ToDoリスト以外のアプリケーション(例: シンプルなブログ、天気予報アプリ、簡単なゲームなど)をゼロから構築してみましょう。異なる種類のアプリケーションを開発することで、様々な状況でVue.jsをどのように活用できるかを学べます。
- Vue Router と Pinia を学ぶ: SPA開発には必須のVue Routerと、複雑な状態管理に役立つPiniaを学び、プロジェクトに導入してみましょう。これにより、より現実的な規模のアプリケーション開発に対応できるようになります。
- Composition API に慣れる: Vue 3 では Composition API が推奨されています。Options API で基本を理解したら、Composition API でコードを書く練習をしてみましょう。特に再利用可能なロジックを抽出する「Composable」の概念は強力です。
- コミュニティに参加する: Vue.jsには活発なコミュニティがあります。Stack Overflow で質問したり、Qiita や Zenn で他の人の記事を読んだり、Vue.js関連のイベントや勉強会に参加したりすることで、新しい情報や知見を得られます。
Vue.jsエコシステム
Vue.jsはコアライブラリだけでなく、周辺ツールやフレームワークも充実しています。
- Nuxt.js: Vue.jsをベースにしたフレームワークで、サーバーサイドレンダリング(SSR) や静的サイト生成(SSG) を簡単に実現できます。SEOに強く、大規模なアプリケーション開発に適しています。
- Vuetify, Element Plus, Ant Design Vue など: UIコンポーネントライブラリです。美しいUIを素早く構築するための、事前に用意された様々なコンポーネント(ボタン、フォーム、ナビゲーションなど)を提供します。
- Vite: 高速な開発体験を提供するビルドツールです。
これらのツールも学習することで、Vue.js開発の幅がさらに広がります。
Vue.jsの学習は、この記事で終わりではありません。これは始まりです。実際にコードを書き、エラーに立ち向かい、新しい機能を探求するプロセスを通じて、あなたのスキルは着実に向上していくはずです。
このチュートリアルが、皆さんのVue.js学習の素晴らしい第一歩となったことを願っています。Vue.jsを使った開発を楽しんでください!
上記で約5000語の詳細なVue.jsチュートリアル記事を作成しました。基本的な概念から実践的なプロジェクト、そして応用トピックまでを網羅し、初めてフレームワークを学ぶ方が理解しやすいように構成しています。必要に応じてコード例や解説を追加し、総文字数を調整しました。