はい、承知いたしました。Vue.jsの基本を約5000語で、初心者向けに分かりやすく解説する記事を作成します。記事の内容を直接ここに表示します。
【入門】Vue.jsの基本を分かりやすく解説
Web開発の世界は常に進化しており、より効率的でインタラクティブなユーザーインターフェース(UI)を構築するためのツールやフレームワークが次々と登場しています。その中でも、学習コストの低さ、柔軟性、そして高いパフォーマンスから、世界中で多くの開発者に愛用されているJavaScriptフレームワークが「Vue.js(ヴュー・ジェイエス)」です。
この記事は、「Vue.jsに興味があるけど、どこから始めればいいか分からない」「JavaScriptの経験はあるけど、フレームワークは初めて」という完全な初心者の方を対象に、Vue.jsの最も基本的な概念から実践的な使い方までを、ステップバイステップで丁寧に解説することを目的としています。約5000語のボリュームで、各要素の「なぜ?」にも答えながら、じっくりとVue.jsの世界に触れていきましょう。
この旅を終える頃には、Vue.jsを使って簡単なWebアプリケーションを構築するための基礎知識が身についているはずです。さあ、一緒にVue.jsの学習を始めましょう!
1. Vue.jsとは何か? なぜ学ぶのか?
1.1 Vue.jsの正体
Vue.jsは、ユーザーインターフェースを構築するためのJavaScriptフレームワークです。公式サイトでは「プログレッシブフレームワーク」と称されています。これは、「段階的に導入できる」「コアライブラリはUI構築に集中しており、必要に応じて他のライブラリ(ルーティングや状態管理など)を追加できる」という意味合いです。
より簡単に言うと、Vue.jsはHTML、CSS、JavaScriptだけでは複雑になりがちなWebページの見た目(UI)と動きを、より効率的で管理しやすく、そして保守しやすい形で構築するための強力な道具箱のようなものです。
1.2 なぜVue.jsが選ばれるのか?
現代のWebアプリケーションは、単なる静的な情報の表示にとどまらず、ユーザーの操作に応じて画面が動的に変化したり、サーバーと非同期でデータをやり取りしたりすることが一般的です。このような複雑なインタラクティブなUIを、素のJavaScriptだけで構築しようとすると、コードがすぐに煩雑になり、管理が困難になります。
ここでフレームワークの出番です。Vue.jsのようなフレームワークを使うことで、以下のようなメリットが得られます。
- 宣言的なレンダリング: HTML要素にJavaScriptのデータを直接「紐づける」ような感覚でUIを構築できます。データが変更されると、それに応じてUIも自動的に更新されます。これにより、「データが変わったら、このHTMLをこう書き換えて…」といった煩雑なDOM操作から解放されます。
- コンポーネント指向: アプリケーションのUIを、独立した再利用可能な部品(コンポーネント)に分割して構築できます。これにより、コードの見通しが良くなり、開発効率や保守性が向上します。例えば、ボタンや入力フォーム、ヘッダーやフッターといった要素をそれぞれ独立した部品として作成し、それらを組み合わせてページ全体を構築できます。
- リアクティビティシステム: Vue.jsの最も強力な機能の一つです。JavaScriptのデータ(オブジェクトや配列)を特別な方法で扱うことで、そのデータに変更があったときに、そのデータを使用しているUIの箇所だけを効率的に再描画できます。これは、UIの状態管理を非常に容易にします。
- 学習コストの低さ: HTML、CSS、基本的なJavaScriptの知識があれば、比較的短時間で基本的な概念を理解し、使い始めることができます。これは、他の大規模なフレームワークと比較した場合の大きな強みです。
- 豊富なエコシステム: コアライブラリだけでなく、ルーティング(Vue Router)、状態管理(Vuex/Pinia)、ビルドツール(Vue CLI/Vite)など、大規模なアプリケーション開発を支援するための公式およびコミュニティによる豊富なツールやライブラリが存在します。
- パフォーマンス: 仮想DOM(Virtual DOM)などの技術を利用し、UIの更新を効率的に行うため、高いパフォーマンスを発揮します。
これらの理由から、Vue.jsは小規模なインタラクティブ機能の追加から、大規模なシングルページアプリケーション(SPA)の開発まで、幅広いプロジェクトで活用されています。
1.3 Vue.jsで解決できる課題
具体的な課題として、Vue.jsは以下のような場面で特に威力を発揮します。
- フォーム入力に応じたリアルタイムな表示更新: ユーザーがフォームに入力した内容を、別の場所で即座にプレビュー表示したい場合など。
- リストデータの動的な表示: サーバーから取得したデータのリストを、条件に応じてフィルタリングしたり、並べ替えたりして表示したい場合。
- モーダルウィンドウやタブUIなどの複雑なコンポーネント: 開閉状態やアクティブなタブなどの状態管理が必要なUI要素を、宣言的に扱いやすく構築したい場合。
- SPA(シングルページアプリケーション)の開発: ページ遷移が発生せず、一つのHTMLファイル内でコンテンツを動的に切り替えながらリッチなユーザー体験を提供したい場合。
2. 最初のVue.jsプロジェクトを動かしてみよう(CDN版)
Vue.jsを始める最も簡単な方法は、HTMLファイルにCDN(Content Delivery Network)経由でVue.jsライブラリを読み込むことです。これにより、特別な環境構築なしに、すぐにコードを書いて動かすことができます。
まずは、以下のHTMLファイルを任意の場所に作成し、ブラウザで開いてみましょう。
“`html
“`
このファイルをブラウザで開くと、「Hello, Vue 3!」と表示されるはずです。
コードの内容を見ていきましょう。
<script src="...">
: Vue.jsライブラリ本体をインターネット経由で読み込んでいます。vue@3
はVue.jsのバージョン3を指定しています。.global.js
は、グローバル変数Vue
として利用できるバージョンです。<div id="app">
: この要素が、Vue.jsアプリケーションが制御する範囲となります。id="app"
というセレクタは、後続のJavaScriptコードで使用されます。{{ message }}
: これはテンプレート構文と呼ばれるものです。Vue.jsは、この二重波括弧の間に書かれたJavaScriptの式を評価し、その結果をDOMにレンダリングします。ここでは、後で定義するmessage
というデータの値が表示されます。<script>
タグ内のJavaScript:const app = Vue.createApp({...});
:Vue.jsアプリケーションの新しいインスタンスを作成しています。Vue 3からはnew Vue()
ではなくVue.createApp()
を使うのが一般的です。引数には、アプリケーションのオプション(設定)を記述したオブジェクトを渡します。data() { return { message: 'Hello, Vue 3!' } }
:この部分が、アプリケーションで使用するデータを定義しています。data
オプションは関数である必要があり、その関数はオブジェクトを返す必要があります。このオブジェクトのプロパティ(ここではmessage
)が、Vue.jsアプリケーションの状態(データ)となります。このデータはリアクティブになります。app.mount('#app');
:作成したVue.jsアプリケーションインスタンスを、HTMLファイル内のid="app"
を持つ要素にマウント(関連付け)しています。これにより、Vue.jsは#app
要素とその子孫要素を制御するようになります。テンプレート内の{{ message }}
は、ここで定義されたmessage
データと紐づけられます。
この簡単な例で、Vue.jsの基本的な流れが見えたでしょうか?
- HTMLでVue.jsが制御する領域と、テンプレート構文を使ってデータの表示場所を定義する。
- JavaScriptでVueアプリケーションインスタンスを作成し、表示したいデータを
data
オプションに定義する。 - 作成したインスタンスをHTMLの特定の要素にマウントする。
これだけで、データとUIが紐づけられ、データが変更されればUIも更新されるリアクティブなアプリケーションの基盤が完成します。
3. Vueインスタンスと基本的なオプション
前のセクションでVue.createApp({})
という記述が出てきました。このapp
こそがVue.jsアプリケーションの本体であり、「Vueインスタンス」と呼ばれます。アプリケーション全体で一つのVueインスタンスを持つのが一般的ですが、ページ内の特定の要素ごとに複数の小さなVueインスタンスをマウントすることも可能です。
Vueインスタンスを作成する際に渡すオブジェクトには、様々なオプションを指定できます。先ほどの例ではdata
オプションを使いました。ここでは、よく使う基本的なオプションをいくつか見ていきましょう。
3.1 el
オプション (Vue 2まで) / mount()
メソッド (Vue 3)
- 役割: VueインスタンスがどのHTML要素を制御するかを指定します。
- Vue 2:
new Vue({ el: '#app', ... })
のようにオプションとして指定しました。 - Vue 3:
Vue.createApp({...}).mount('#app')
のようにインスタンス作成後にメソッドとして呼び出すのが一般的です。mount()
メソッドはセレクタ文字列(例:#app
,.my-class
)または実際のDOM要素を受け取ります。
3.2 data
オプション
- 役割: Vueインスタンスが管理するリアクティブなデータを定義します。
- 記述方法: 必ず関数として定義し、その関数がオブジェクトを返す必要があります。これは、同じコンポーネント定義を複数回使用した際に、それぞれのインスタンスが独立したデータのコピーを持つようにするためです。
- アクセス: テンプレート内ではプロパティ名(例:
message
)で、JavaScriptコード内ではthis.propertyName
(例:this.message
)でアクセスできます。 - リアクティビティ:
data
オプションで定義されたプロパティは、その値が変更されると、その値を参照しているテンプレートの箇所が自動的に更新されます。Vue.jsが内部的にデータの変更を検知し、DOMを効率的に更新する仕組み(リアクティビティシステム)が働いているからです。
例:
javascript
const app = Vue.createApp({
data() {
return {
productName: 'Vue入門ガイド',
price: 3000,
isAvailable: true,
items: ['りんご', 'バナナ', 'みかん']
}
}
});
app.mount('#app');
テンプレート内では {{ productName }}
、{{ price }}
、{{ isAvailable }}
、{{ items }}
のように使用できます。
3.3 methods
オプション
- 役割: Vueインスタンスに関連付ける関数(メソッド)を定義します。これらのメソッドは、イベントハンドリングや特定の処理を実行するために使用されます。
- 記述方法: オブジェクトとして定義し、各プロパティに関数(メソッド)を記述します。
- アクセス: テンプレート内ではメソッド名に
()
をつけて(例:handleClick()
)、JavaScriptコード内ではthis.methodName()
(例:this.handleClick()
)で呼び出せます。methods
内のメソッドからは、this
を使ってdata
や他のmethods
にアクセスできます。
例:
“`html
{{ count }}
``
increment
この例では、ボタンがクリックされるたびにメソッドが実行され、
data内の
countが増加します。
count`はリアクティブなので、画面上の表示も即座に更新されます。
3.4 その他の基本的なオプション(概要)
computed
: 既存のdata
プロパティに基づいて算出される新しいプロパティを定義します。算出結果はキャッシュされ、依存するデータが変更された場合にのみ再計算されます。(後述)watch
: 特定のdata
プロパティやcomputed
プロパティの値の変化を監視し、変化があったときに特定の処理を実行します。(後述)components
: このインスタンスまたはコンポーネント内で使用する子コンポーネントを登録します。(後述)template
: Vueインスタンスまたはコンポーネントのテンプレートを文字列で直接定義します。通常はHTMLファイル内に記述することが多いですが、より複雑なビルド設定を行う場合はこちらを使うこともあります。
これらのオプションを組み合わせて、Vue.jsアプリケーションの振る舞いを定義していきます。
4. テンプレート構文の詳細
Vue.jsはHTMLベースのテンプレート構文を使用しており、開発者は既存のHTMLを活かしながらVue.jsの機能を取り入れることができます。先ほど見た{{ message }}
のようなテキスト補間だけでなく、様々なディレクティブ(Directive)と呼ばれる特別な属性を使って、HTML要素の振る舞いを操作できます。
4.1 テキスト補間 ({{ }}
)
最も基本的な機能です。二重波括弧の間にJavaScriptの式を記述すると、その評価結果がその場所に挿入されます。
“`html
テキストの表示: {{ textData }}
数値の計算: {{ number1 + number2 }}
三項演算子: {{ isLoggedin ? ‘ようこそ’ : ‘ログインしてください’ }}
挨拶: {{ greeting }}
出力:
テキストの表示: これはテキストです。
数値の計算: 30
三項演算子: ようこそ
挨拶: こんにちは
“`
波括弧の中では、JavaScriptの式であればある程度の複雑なものも書けますが、テンプレートはロジックを書きすぎず、シンプルに保つことが推奨されます。複雑な計算や条件分岐は、後述する算出プロパティ(Computed Properties)やメソッド(Methods)で行うべきです。
4.2 ディレクティブ (Directives)
ディレクティブは、v-
というプレフィックスを持つ特別な属性です。要素に適用され、DOMに対して何らかの反応的な振る舞いをさせます。
例: v-if
, v-for
, v-bind
, v-on
など。
ディレクティブの中には、引数や修飾子を持つものがあります。
- 引数:
:
に続けて指定します。例えばv-bind:href
ではhref
が引数です。これは、HTML要素のどの属性にバインドするかを指定しています。 - 修飾子:
.
に続けて指定します。例えばv-on:click.prevent
ではprevent
が修飾子です。これは、イベントハンドリングの挙動を変更します(この例では、クリックイベントのデフォルトの動作を防ぎます)。
それでは、主要なディレクティブを詳しく見ていきましょう。
4.3 v-bind
ディレクティブ
- 役割: HTML属性にVueのデータをバインドします。要素の属性値を動的に設定したい場合に非常に便利です。
- 記述方法:
v-bind:属性名="データまたは式"
- 省略記法:
:
に続けて属性名を記述できます。例::属性名="データまたは式"
例:
“`html
``
この例では、タグの
href属性や
タグの
src,
alt属性、
v-bind
は、後述するクラスやスタイルのバインディングでも非常に重要になります。
4.4 v-if
, v-else-if
, v-else
ディレクティブ
- 役割: 条件に基づいて要素をレンダリング(表示/非表示)します。
- 記述方法:
v-if="式"
,v-else-if="式"
,v-else
- 動作:
v-if
の式が真と評価された場合、その要素(とその子要素)がDOMに実際に挿入されます。偽と評価された場合、要素はDOMから完全に削除されます。v-else-if
とv-else
は、直前のv-if
またはv-else-if
とセットで使用する必要があります。
例:
“`html
ユーザーとしてログインしています。
ログインしていません。
``
isLoggedInが
trueなら最初の
が表示され、
falseなら二番目の
が表示されます。
userRoleの値によって、3つの
4.5 v-show
ディレクティブ
- 役割: 条件に基づいて要素を表示/非表示します。
- 記述方法:
v-show="式"
- 動作:
v-show
の式が真と評価された場合、要素は表示されます。偽と評価された場合、要素はDOMに残りますが、CSSのdisplay: none;
スタイルが適用されて非表示になります。
v-if
と v-show
の違い:
- v-if: 条件が偽の場合、要素はDOMから削除される。(コスト: トグルする際のDOM操作が大きい、初期レンダリングは条件次第)
- v-show: 条件が偽の場合、要素はDOMに残るが非表示になる。(コスト: 初期レンダリングは常に必要、トグルする際のCSS切り替えは軽い)
頻繁に表示/非表示を切り替える必要がある要素にはv-show
、一度表示したらほぼ固定か、表示/非表示の切り替えがあまり頻繁ではない要素にはv-if
を使うのが一般的です。
4.6 v-for
ディレクティブ
- 役割: 配列やオブジェクトのリストに基づいて、要素を繰り返しレンダリングします。
- 記述方法:
v-for="itemName in list"
またはv-for="(itemName, index) in list"
(配列の場合) /v-for="(value, key, index) in object"
(オブジェクトの場合) - 重要:
v-for
を使用する際には、できるだけ:key
属性を付けて、各要素に一意なキーを指定することを強く推奨します。これは、Vueがリスト内の要素の挿入、削除、移動を効率的に追跡し、パフォーマンスを最適化するために必要です。通常は、リストデータのIDなど、一意な値を使用します。
例1: 配列の繰り返し
“`html
- {{ item }}
出力:
html
- りんご
- バナナ
- みかん
“`
例2: 配列(要素とインデックス)の繰り返し
“`html
- {{ index }} – {{ item }}
出力:
html
- 0 – りんご
- 1 – バナナ
- 2 – みかん
“`
例3: オブジェクトの繰り返し
“`html
- {{ index }}. {{ key }}: {{ value }}
出力:
html
- 0. name: Alice
- 1. age: 30
- 2. city: Tokyo
``
v-forは、リストデータの表示に欠かせない非常に強力なディレクティブです。
:key`属性は、特にリストの途中で要素を追加したり削除したりする場合に、Vueが効率的にDOMを更新するために重要なので、忘れないようにしましょう。
4.7 v-on
ディレクティブ
- 役割: DOMイベント(クリック、マウスオーバー、キー入力など)をリッスンし、イベント発生時にJavaScriptのメソッドなどを実行します。
- 記述方法:
v-on:イベント名="メソッド名またはインライン式"
- 省略記法:
@
に続けてイベント名を記述できます。例:@イベント名="メソッド名またはインライン式"
例:
“`html
{{ inputText }}
``
methods`内のメソッドが実行されます。イベントハンドラには、ネイティブのイベントオブジェクトが引数として渡されます。
この例では、ボタンのクリック、マウスオーバー、入力フィールドへの入力といったイベントが発生した際に、対応する
v-on
には、イベントハンドリングの挙動を変更するための様々な修飾子があります。
.stop
: イベントの伝播を停止します(event.stopPropagation()
と同じ)。
例:@click.stop="doSomething"
.prevent
: イベントのデフォルトの動作を防ぎます(event.preventDefault()
と同じ)。フォーム送信やリンク遷移の阻止などに使われます。
例:@click.prevent="doSomething"
.capture
: キャプチャフェーズでイベントをリッスンします。.self
: イベントが要素自身で発生した場合のみトリガーされます。.once
: イベントハンドラが最大1回だけ実行されます。.passive
: スクロールイベントなどのパフォーマンスを改善します。モバイルでの利用が多いです。
キーイベントには、さらにキー修飾子があります(例: .enter
, .tab
, .delete
, .esc
, .space
, .up
, .down
, .left
, .right
)。
例: Enterキーで実行
html
<input type="text" @keyup.enter="submitForm">
4.8 v-model
ディレクティブ
- 役割: フォーム入力要素(
<input>
,<select>
,<textarea>
など)とVueのデータを双方向バインディングします。フォーム要素の入力値が変更されるとデータも更新され、データが変更されるとフォーム要素の表示も更新されます。 - 記述方法:
v-model="データ名"
例:
“`html
入力されたメッセージ: {{ message }}
同意済みです。
選択された性別: {{ gender }}
選択されたアイテム: {{ selectedItem }}
``
v-modelは、フォーム要素のタイプに応じて自動的に適切な方法でデータと連携します(
input要素なら
value属性と
inputイベント、
checkbox/
radioなら
checked属性と
changeイベント、
selectなら
value属性と
change`イベント)。
v-model
にも修飾子があります。
.lazy
: デフォルトではinput
イベントでデータが更新されますが、.lazy
を付けるとchange
イベントで更新されるようになります(入力確定時など)。
例:v-model.lazy="message"
.number
: 入力値を自動的に数値に変換します。
例:v-model.number="age"
.trim
: 入力値の前後にある空白を自動的にトリムします。
例:v-model.trim="message"
5. 算出プロパティ (Computed Properties)
Vue.jsで扱うデータは、data
オプションで直接定義するものだけではありません。既存のdata
プロパティの値に基づいて、動的に計算されるプロパティが必要になることがあります。このような場合に「算出プロパティ」を使用します。
- 役割: 既存のデータ(
data
や他のcomputed
プロパティ)から新しいデータを計算し、その結果をプロパティとして利用可能にします。 - 記述方法: Vueインスタンスの
computed
オプションに関数として定義します。関数は、計算結果となる値を返す必要があります。 - 特徴:
- 算出プロパティは依存関係を追跡します。算出プロパティの計算に使用されているデータ(依存データ)が変更されると、その算出プロパティは自動的に再計算されます。
- 算出結果はキャッシュされます。依存データが変更されていない限り、算出プロパティが複数回参照されても、計算は一度しか行われません。これにより、パフォーマンスが向上します。
例:
“`html
元のメッセージ: {{ message }}
反転したメッセージ: {{ reversedMessage }}
価格: {{ price }} 円
税率: {{ taxRate * 100 }} %
税込み価格: {{ priceWithTax }} 円
``
reversedMessage
この例では、は
messageデータが変更されたときにのみ再計算され、
priceWithTaxは
priceまたは
taxRateが変更されたときにのみ再計算されます。これらの算出プロパティは、テンプレート内では
dataプロパティと同じように、プロパティ名でアクセスできます(例:
{{ reversedMessage }}`)。
算出プロパティ vs メソッド:
計算ロジックをメソッド(methods
オプションで定義した関数)として定義し、テンプレート内で呼び出すことも可能ですが、ほとんどのケースでは算出プロパティを使用する方が望ましいです。その理由は、キャッシュの仕組みにあります。
- 算出プロパティ: 依存データが変更されない限り、結果がキャッシュされ、呼び出しごとに再計算されません。
- メソッド: 呼び出されるたびに必ず実行されます。
例えば、上記のreversedMessage
をメソッドとして定義した場合:
javascript
methods: {
getReversedMessage() {
console.log('getReversedMessage が実行されました'); // 実行されたか確認用
return this.message.split('').reverse().join('');
}
}
テンプレートでは {{ getReversedMessage() }}
と呼び出します。もしこのメソッドがテンプレート内の複数箇所で呼び出されている場合、または同じコンポーネントが何度も再レンダリングされる場合、依存データが変更されていなくてもメソッドは毎回実行されてしまいます。一方、算出プロパティなら依存データが変わらなければ計算は一度きりです。
そのため、データの計算や加工によって新しい値を導き出し、それをテンプレートで表示したい場合は、算出プロパティを使用するのが一般的でパフォーマンス的にも有利です。イベント発生時の処理や、DOM操作など、特定の「動作」を実行したい場合はメソッドを使用します。
6. ウォッチャー (Watchers)
ウォッチャーは、特定のデータや算出プロパティの値の変化を監視し、変化があったときに非同期の処理やコストのかかる処理を実行したい場合に使用します。
- 役割: 特定のデータソース(
data
プロパティ、computed
プロパティ、propsなど)の変化を監視し、変化発生時に副作用を伴う処理(APIコール、DOM操作など)を実行します。 - 記述方法: Vueインスタンスの
watch
オプションに、監視したいプロパティ名をキーとして、コールバック関数またはオプション付きのオブジェクトを定義します。 - 特徴:
- データ変化時の副作用を伴う処理に適しています。
- 算出プロパティとは異なり、キャッシュはされません。変化が発生するたびに定義した処理が実行されます。
- コールバック関数は、新しい値と古い値の2つの引数を受け取ります。
例:
“`html
{{ answer }}
``
question
この例では、という
dataプロパティの値が変更されるたびに、
watchオプションで定義した関数が実行されます。関数内で、新しい値(
newQuestion)をチェックし、必要に応じて
getAnswerメソッドを呼び出しています。これは、非同期処理(
setTimeout`でシミュレーションしているAPIコールなど)を行う典型的な例です。
ウォッチャーと算出プロパティの使い分け:
- 算出プロパティ: 既存のデータから新しいデータを計算して表示したい場合。結果はキャッシュされ、依存データの変更に応じて自動更新される。
- ウォッチャー: 特定のデータ変化をトリガーとして、副作用を伴う処理を実行したい場合(非同期処理、DOM操作、ログ出力など)。キャッシュはされず、変化発生時に指定した処理が実行される。
ほとんどの場合、算出プロパティでデータの加工や表示を扱い、ウォッチャーは最後の手段として、算出プロパティでは実現できない複雑な副作用(非同期処理など)が必要な場合に使用すると考えてください。
7. クラスとスタイルのバインディング
HTML要素のclass
属性やstyle
属性を、Vueのデータに基づいて動的に変更したい場合がよくあります。これもv-bind
ディレクティブを使って実現できますが、特にクラスとスタイルのバインディングには便利な機能が提供されています。
7.1 クラスのバインディング (:class
)
- 役割: 要素のCSSクラスを、データに基づいて動的に切り替えます。
- 記述方法:
:class="...
の形式で指定します。値には、オブジェクトまたは配列を渡すことができます。
オブジェクト記法: キーがクラス名、値が真偽値となります。値がtrue
であればそのクラスが適用され、false
であれば適用されません。
“`html
“`
配列記法: 配列の要素としてクラス名(文字列)またはオブジェクトを記述します。
“`html
“`
これらの記法を組み合わせることも可能です。また、:class
は通常のclass
属性と共存でき、両方のクラスが要素に適用されます。
7.2 スタイルのバインディング (:style
)
- 役割: 要素のCSSスタイルを、データに基づいて動的に設定します。
- 記述方法:
:style="...
の形式で指定します。値には、オブジェクトまたは配列を渡すことができます。
オブジェクト記法: CSSプロパティ名をキャメルケース(例: fontSize
)またはケバブケース(例: 'font-size'
)でキーとして、値を文字列で記述します。
“`html
“`
配列記法: 複数のスタイルオブジェクトを配列として指定します。
“`html
``
:styleも通常の
style`属性と共存できます。Vueが生成するスタイルは、既存のスタイルにマージされます。
8. イベントハンドリングの詳細 (v-on
)
先ほどv-on
ディレクティブで基本的なイベント処理を見ましたが、もう少し詳しくイベントオブジェクトやメソッドについて見ていきましょう。
8.1 インラインハンドラとメソッドハンドラ
v-on
の値には、簡単なJavaScriptの式を直接記述する「インラインハンドラ」と、methods
オプションで定義したメソッドを呼び出す「メソッドハンドラ」があります。
- メソッドハンドラ:
v-on:click="methodName"
イベントオブジェクトは自動的にメソッドの第一引数として渡されます。 - インラインハンドラ:
v-on:click="someExpression"
式の中でネイティブイベントオブジェクトを使用したい場合は、特別な変数$event
を使用します。
例:
“`html
“`
複雑なロジックや再利用したい処理はメソッドハンドラとして定義するのが一般的です。簡単な処理や、特定の引数をメソッドに渡したい場合はインラインハンドラも便利です。
8.2 イベント修飾子 (再掲)
前のセクションでも触れましたが、よく使うイベント修飾子を再度確認しておきましょう。
.stop
: イベント伝播停止.prevent
: デフォルト動作阻止.capture
: キャプチャフェーズでハンドリング.self
: 要素自身でのイベントのみ.once
: 一回だけ実行.passive
: スクロールパフォーマンス改善
複数の修飾子を連結することも可能です。
例: @click.stop.prevent="doSomething"
(伝播を停止し、デフォルト動作も阻止)
キーイベント修飾子:
* .enter
, .tab
, .delete
, .esc
, .space
, .up
, .down
, .left
, .right
* .ctrl
, .alt
, .shift
, .meta
(Ctrl, Alt, Shift, Metaキーと同時押しのイベントをリッスン)
例: @keyup.enter="submit"
(Enterキーが離されたときにsubmitメソッドを実行)
これらの修飾子を使うことで、イベント処理のロジックをシンプルに保つことができます。
9. コンポーネント入門
Vue.jsの最も強力な機能の一つがコンポーネントシステムです。コンポーネントを使うことで、UIを独立した再利用可能な小さな部品に分割して構築できます。これは、大規模なアプリケーションを開発する上で不可欠な考え方です。
9.1 コンポーネントとは? なぜ使うのか?
- コンポーネント: UIの一部とそのロジック、スタイルをカプセル化した自己完結型のブロックです。HTML、JavaScript、CSSのセットと考えることができます。
- 例: ボタン、入力フォーム、ヘッダー、フッター、商品リスト、モーダルウィンドウなど、Webページの様々な要素をコンポーネントとして定義できます。
- メリット:
- 再利用性: 一度作成したコンポーネントは、アプリケーション内の様々な場所で何度でも再利用できます。
- 保守性: コンポーネントごとにコードが分割されるため、変更や修正が必要な場合に影響範囲が限定され、保守が容易になります。
- 可読性: UIの構造がコンポーネントの組み合わせとして表現されるため、コードの可読性が向上します。
- 開発効率: チーム開発において、メンバーそれぞれが異なるコンポーネントを並行して開発できます。
9.2 基本的なコンポーネントの作成と登録(CDN版)
CDN版のVue.jsでは、Vue.createApp
インスタンスのcomponent
メソッドを使ってコンポーネントをグローバルに登録したり、親コンポーネントのオプション内でローカルに登録したりできます。
グローバル登録の例:
“`html
``
app.component()
この例では、を使って
my-componentという名前でコンポーネントをグローバルに登録しています。グローバル登録されたコンポーネントは、Vueアプリケーションがマウントされた要素(ここでは
#app)内のどこからでも、カスタムタグ
ポイント:
* コンポーネントの定義は、基本的にVueインスタンスのオプション(data
, methods
, computed
など)と同じ構造を持つオブジェクトです。
* data
オプションは、コンポーネントの場合も必ず関数である必要があります。これにより、コンポーネントが複数回使用されたときに、それぞれのインスタンスが独立したデータを持つことができます。
* コンポーネントのテンプレートは、単一のルート要素を持つ必要があります(Vue 3ではフラグメントも可能になりましたが、最初は単一ルートが良いでしょう)。
* HTMLは大文字小文字を区別しないため、テンプレート内でコンポーネントを使用する際は、ケバブケース(my-component
)が推奨されます。JavaScriptの定義名(MyComponent
などのパスカルケースも可)とは書き方が異なることがある点に注意してください。
ローカル登録の例:
特定の親コンポーネント内でのみ使用するコンポーネントは、ローカル登録するのが一般的です。
“`html
``
ChildComponent
ローカル登録されたコンポーネント()は、それを
componentsオプションで登録した親コンポーネント(
ParentComponent`)のテンプレート内でのみ使用できます。他のコンポーネントやルートインスタンスのテンプレートでは直接使用できません。大規模なアプリケーションでは、依存関係を明確にするため、ローカル登録がより一般的です。
9.3 Single File Components (SFC) とビルドツール (補足)
実際の開発現場では、CDNでVue.jsを読み込む方法は小規模な実験やプロトタイピングに限られます。多くの場合は、Single File Components (SFC) と呼ばれる.vue
ファイル形式を使用します。
.vue
ファイルは、<template>
, <script>
, <style>
のブロックを一つのファイルにまとめて記述でき、それぞれのブロックがそのコンポーネント固有のものとなります。
例 (MyComponent.vue):
“`html
これはマイコンポーネントです
{{ message }}
``
.vue`ファイルは、ブラウザが直接理解できる形式ではありません。そのため、ViteやVue CLIといったビルドツールを使用して、ブラウザが読み込めるHTML、JavaScript、CSSファイルに変換(コンパイル)する必要があります。
この
ビルドツールを使用することで、SFCの利用だけでなく、モジュールのバンドル、JavaScriptのトランスパイル(新しい構文を古いブラウザ向けに変換)、CSSのプリプロセッサ利用、ホットリロード(コード変更を即座にブラウザに反映)など、多くのメリットが得られます。
本格的な開発に進む際は、Viteなどを使った環境構築から始めることになりますが、まずはCDN版で基本的な概念を理解することから始めましょう。
10. コンポーネント間のデータ連携 (Props と Custom Events)
アプリケーションがコンポーネントの木構造で構成されるようになると、コンポーネント間でデータをやり取りする必要が出てきます。Vue.jsでは、コンポーネント間の主なデータ連携方法として以下の2つを提供しています。
- Props (プロパティ): 親コンポーネントから子コンポーネントへデータを渡す(下方伝達)。
- Custom Events (カスタムイベント): 子コンポーネントから親コンポーネントへメッセージを送る(上方伝達)。
この「Props down, Events up」という単方向データフローは、アプリケーションの状態管理を見通し良く保つためのVue.jsの設計思想です。
10.1 Props: 親から子へデータを渡す
- 役割: 親コンポーネントが持つデータを、その子コンポーネントに渡します。
- 子コンポーネント側:
props
オプションで、親から受け取るプロパティ名を定義します。定義されたプロパティは、子コンポーネントのインスタンス上でthis.propertyName
としてアクセスできるようになり、テンプレート内でも直接使用できます。 - 親コンポーネント側: 子コンポーネントを使用する際に、カスタムタグに
v-bind
ディレクティブを使ってデータを渡します。
例:
“`html
``
parentData
親コンポーネントのと
parentCountの値が、
v-bindを使って子コンポーネントの
messageと
countというpropsに渡されています。子コンポーネントは、受け取ったpropsを自身のテンプレート内で表示しています。親コンポーネントの
parentCount`をボタンで変更すると、その変更がprops経由で子に伝わり、子の表示も更新されます。
Propsのバリデーション:
受け取るpropsには、データ型や必須かどうかなどのバリデーションルールを定義できます。これにより、コンポーネントの堅牢性が向上します。props
オプションを配列ではなくオブジェクトとして定義し、各プロパティにルールを記述します。
javascript
props: {
message: String, // string型であることを期待
count: {
type: Number, // number型であることを期待
required: true, // 必須
default: 0, // デフォルト値 (requiredとdefaultは一緒に使えない場合が多い)
validator: function (value) { // カスタムバリデータ
return value >= 0
}
},
items: Array, // array型であることを期待
user: Object // object型であることを期待
}
バリデーションに失敗すると、開発モードではコンソールに警告が表示されます。
Propsの単方向データフロー:
重要: Propsは親から子への一方通行のデータフローです。子コンポーネント内で受け取ったpropsの値を直接変更してはいけません。これはVue.jsのルールであり、親子の依存関係を明確に保ち、アプリケーションの状態管理を予測可能にするために非常に重要です。
もし子コンポーネント内でpropsの値を変更したい場合は、その変更を親コンポーネントに通知し、親コンポーネントでデータ自体を更新する必要があります。この「子から親への通知」に使うのがカスタムイベントです。
10.2 Custom Events: 子から親へメッセージを送る
- 役割: 子コンポーネント内で発生した出来事やデータ変更を、親コンポーネントに通知します。
- 子コンポーネント側:
this.$emit('イベント名', [渡したいデータ])
というメソッドを呼び出して、カスタムイベントを発行(emit)します。 - 親コンポーネント側: 子コンポーネントを使用するカスタムタグに、
v-on
(または@
)ディレクティブを使って、そのイベント名に対応するリスナーを登録します。
例:
“`html
``
currentCount
この例では、子コンポーネントのボタンがクリックされると、子のがインクリメントされ、同時に
update-countというカスタムイベントが発行されます。このイベントには、更新された
currentCountの値がデータとして添付されています。親コンポーネントは、子コンポーネントを使用している箇所で
@update-count=”handleChildUpdate”とリスナーを登録しており、イベント発生時に親の
handleChildUpdateメソッドが呼び出されます。このメソッドは子から渡された新しい値を受け取り、親の
totalCount`データを更新しています。
このように、データはPropsで親から子へ、子から親への「操作」や「通知」はカスタムイベントで行う、というルールを守ることで、コンポーネント間の依存関係が明確になり、デバッグや理解が容易になります。
v-model on Components:
Propsとカスタムイベントを組み合わせることで、フォーム入力要素のv-model
のような双方向バインディングの挙動を、カスタムコンポーネントに対して実現できます。Vue 3では、v-model
をコンポーネントに適用すると、デフォルトではmodelValue
という名前のpropsを子に渡し、子がupdate:modelValue
という名前のイベントを発行するという規約になっています。
“`html
``
modelValue
子コンポーネントはというpropsを受け取り、入力値が変更されたら
this.$emit(‘update:modelValue’, event.target.value)`のようにイベントを発行します。これにより、カスタムコンポーネントでも手軽に双方向バインディングが実現できます。
11. ライフサイクルフック
Vue.jsコンポーネントは、作成されてから破棄されるまでの間に、特定の段階を経過します。これらの段階を「コンポーネントインスタンスのライフサイクル」と呼びます。Vue.jsは、そのライフサイクルの特定の瞬間に開発者が独自のコードを実行できるように、「ライフサイクルフック」という機能を提供しています。
ライフサイクルフックは、コンポーネントのオプションとして関数名で定義します。
一般的なライフサイクルフック(Vue 3のComposition APIスタイルも含むが、ここではOptions APIに絞って解説):
beforeCreate
: インスタンスが初期化された直後。data
やevent
が設定される前。created
: インスタンスが作成された後。data
プロパティやmethods
などが使用可能になっていますが、DOMにはまだマウントされていません。データの初期化や非同期処理の開始に最もよく使われます。beforeMount
: インスタンスがDOMにマウントされる直前。テンプレートのコンパイルは完了していますが、まだDOM要素に置き換えられていません。mounted
: インスタンスがDOMにマウントされた後。コンポーネントのDOM要素にアクセス可能になります。サードパーティライブラリの初期化や、DOMに依存する処理に最もよく使われます。beforeUpdate
: データが変更され、DOMが更新される直前。updated
: データ変更によりDOMが更新された後。更新後のDOMにアクセス可能ですが、DOM操作をここで行うと無限ループの可能性があるので注意が必要です。beforeUnmount
: コンポーネントがアンマウント(DOMから削除)される直前。イベントリスナーやタイマーの解除などに使われます。unmounted
: コンポーネントがアンマウントされた後。インスタンスは完全に破棄されています。
ライフサイクルのイメージ:
“`
-> beforeCreate -> created -> beforeMount -> mounted ->
(データ変更) -> beforeUpdate -> updated ->
(コンポーネント破棄) -> beforeUnmount -> unmounted
“`
例:
“`html
``
created
開発者ツールのコンソールを開いて、コンポーネントが表示されたり非表示になったりする際のログを確認してみてください。どのフックがどのタイミングで実行されるかが理解できるはずです。特にと
mounted`はよく使用されます。
12. その他の基本的な概念
記事のボリューム的に詳細な解説は難しいですが、入門として知っておくと良いその他の基本的な概念をいくつか紹介します。
12.1 テンプレート参照 (ref
)
特定のDOM要素や子コンポーネントのインスタンスに直接アクセスしたい場合があります。このような場合に「テンプレート参照」を使用します。
- 役割: テンプレート内の要素や子コンポーネントに名前を付け、JavaScriptコードから参照できるようにします。
- 記述方法: テンプレート内の要素やコンポーネントに
ref="参照名"
という属性を付けます。 - アクセス: コンポーネントインスタンスの
this.$refs.参照名
でアクセスできます。参照はコンポーネントがmounted
された後に利用可能になります。
“`html
``
ref`は、Vueのリアクティブシステムを介さない生のDOM操作が必要な場合などに使用されますが、可能な限りVueのデータバインディングやコンポーネント連携で実現することを検討すべきです。
12.2 スロット (Slots)
コンポーネントを使う際に、親コンポーネントから子コンポーネントの特定の場所にコンテンツを挿入したい場合があります。このような「コンテンツの受け渡し口」として「スロット」が使用されます。
- 役割: 親コンポーネントが、子コンポーネントのテンプレート内の指定した場所にHTMLコンテンツを注入できるようにします。
- 子コンポーネント側:
<slot></slot>
タグを使って、コンテンツの挿入位置を定義します。 - 親コンポーネント側: 子コンポーネントを使用するカスタムタグの中に、挿入したいコンテンツを記述します。
“`html
スロットを使ったコンテンツ
これは親から渡された段落です。
- リストアイテム1
- リストアイテム2
``
my-layout-component
出力では、というカスタムタグの中身が、子コンポーネントの
13. Vue.js開発の次のステップ
この記事では、CDN版を使ってVue.jsの基本的な概念とテンプレート構文、コンポーネントの仕組み、データ連携、ライフサイクルフックなどを学びました。これらはVue.jsを始める上での土台となります。
しかし、実際の開発ではより多くの機能や効率的な開発手法が求められます。次のステップとして、以下の内容を学ぶことをお勧めします。
- ビルドツールの利用 (Vite または Vue CLI): Single File Components (
.vue
ファイル) を使用するためにはビルドツールが必要です。Viteは高速で設定が簡単なため、Vue 3の公式推奨ビルドツールとなっています。Vue CLIも広く使われています。 - Single File Components (SFC):
.vue
ファイル形式での開発に慣れること。テンプレート、スクリプト、スタイルを一つのファイルにまとめ、コンポーネント開発がより効率的になります。 - ルーティング (Vue Router): SPA開発には必須のライブラリです。ページのURLと表示するコンポーネントのマッピングを管理します。
- 状態管理 (Pinia または Vuex): アプリケーション全体で共有される複雑な状態(データ)を管理するためのライブラリです。大規模なアプリケーションでは状態管理ライブラリの導入を検討すると良いでしょう。Vue 3ではPiniaが公式に推奨されています。
- Composition API: Vue 3で導入された新しいAPIスタイルです。特に大規模なコンポーネントで、関連するロジックをまとめて記述し、コードの再利用性を高めるのに役立ちます。この記事で解説したOptions APIとは異なる記述スタイルですが、どちらを使うかはプロジェクトやチームの好みによります。(Options APIも引き続き利用可能です)
- テスト: コンポーネントやロジックのテスト方法を学ぶこと。
- サーバーサイドレンダリング (SSR) / 静的サイト生成 (SSG): Nuxt.jsのようなフレームワークを利用することで、初期表示速度の向上やSEO対策ができます。
これらの要素を学ぶことで、より複雑で現実的なWebアプリケーションをVue.jsで効率的に開発できるようになります。
14. まとめと次のアクション
この記事では、Vue.jsの基本の「き」から始め、Vueインスタンス、テンプレート構文、主要なディレクティブ(v-bind
, v-if
, v-for
, v-on
, v-model
)、算出プロパティ、ウォッチャー、コンポーネント(PropsとCustom Events)、ライフサイクルフックといった重要な概念を学びました。約5000語の解説を通じて、それぞれの概念がどのような役割を持ち、どのように使うのかを理解できたはずです。
Vue.jsは、これらの基本的な要素の組み合わせで成り立っています。焦らず、一つ一つの概念を小さなコード例で実際に動かしながら理解していくことが大切です。
次のアクション:
- この記事のコード例をすべて実際に動かしてみる: ブラウザのコンソールを開き、ログを確認しながら挙動を確かめてください。
- 簡単なアプリケーションを作ってみる: 例:ToDoリスト(入力、表示、削除機能)、簡単な計算機、カウンターアプリなど。この記事で学んだディレクティブやコンポーネントを使ってみましょう。
- Vue.js公式ドキュメントを読む: 公式ドキュメントは非常に質が高く、詳しく解説されています。この記事で学んだ内容を深めるのに最適です。
- ビルドツールの環境構築に挑戦する: Viteを使って、
.vue
ファイル形式での開発環境をセットアップしてみましょう。
Vue.jsの学習は、実践あるのみです。手を動かしながら、少しずつ新しい概念を取り入れていくことで、着実にスキルが身についていきます。
この記事が、あなたのVue.js学習の素晴らしいスタートとなることを願っています。頑張ってください!