Vue.js の始め方|初心者向け最速チュートリアル
はじめに:Vue.jsの世界へようこそ!
Web開発の世界に飛び込む皆さん、こんにちは!
あなたは今、「もっとモダンな、効率的なWebサイトやWebアプリケーションを作ってみたい」「インタラクティブなUIを簡単に実装したい」と考えているかもしれません。あるいは、「ReactやAngularといった他のフレームワークもあるけれど、Vue.jsが良いと聞いた」という方もいるでしょう。
まさにその願いを叶える強力なツールの一つが、今回ご紹介するVue.jsです。
Vue.jsは、ユーザーインターフェース(UI)を構築するためのプログレッシブなJavaScriptフレームワークです。プログレッシブ、というのは、必要に応じて少しずつ導入できる柔軟性を持っているという意味です。小さな機能追加から、大規模なシングルページアプリケーション(SPA)開発まで、幅広い用途に対応できます。
Vue.jsが多くの開発者に愛されている理由は何でしょうか?
- 学習コストの低さ: HTML、CSS、JavaScriptの基本的な知識があれば、比較的簡単に学習を始められます。直感的で分かりやすいAPI設計が特徴です。
- 高い柔軟性: CDNから読み込んで数行のコードで始めたり、CLI(コマンドラインインターフェース)を使って本格的なプロジェクトを構築したりと、プロジェクトの規模や要件に合わせて様々な方法で導入できます。
- 優れたパフォーマンス: 軽量で高速です。仮想DOMを採用しており、効率的なDOM操作を実現します。
- 豊富なエコシステム: 公式のルーター(Vue Router)や状態管理(Pinia/Vuex)ライブラリがあり、大規模開発を強力にサポートします。
- 開発のしやすさ: 単一ファイルコンポーネント(Single File Component – SFC)という形式を使うことで、HTML, CSS, JavaScriptを一つのファイルにまとめて記述でき、コンポーネントごとにカプセル化された開発が可能です。
この記事は、Web開発の基本(HTML, CSS, JavaScript)は一通り学習したけれど、Vue.jsは全く触ったことがない、という初心者の方を対象としています。
この記事を読むことで、以下の内容を習得できます。
- Vue.jsの基本的な考え方
- Vue.jsの開発環境の構築方法(CDNを使った最速導入と、CLIを使った本格的な導入)
- Vue.jsのテンプレート構文、ディレクティブ、イベント処理、フォームバインディングなどの基本
- コンポーネントの基本的な使い方
- 簡単なアプリケーション(Todoリスト)の実装を通じて、実践的なVue.jsの使い方
さあ、Vue.jsの世界へ飛び込んで、モダンなWeb開発の楽しさを体験しましょう!
Vue.jsを始める前に:準備体操
Vue.jsでの開発を始める前に、いくつか準備しておきたいものと、確認しておきたい知識があります。
必要なもの
- PC: Windows, macOS, Linux など、お好みのOSが搭載されたコンピュータ。
- コードエディタ: VS Code, Sublime Text, Atom など、使い慣れたエディタを用意しましょう。特にVS CodeはVue.js開発用の拡張機能が豊富でおすすめです。
- モダンなWebブラウザ: Google Chrome, Firefox, Safari, Edge など。開発者ツールを使ってデバッグを行います。特にChromeのVue Devtools拡張機能は必須レベルで便利です。
- インターネット環境: ライブラリのダウンロードなどで必要になります。
- コマンドラインツール: ターミナル (macOS/Linux) または コマンドプロンプト/PowerShell (Windows)。後述するCLIを使う場合に必要です。
確認しておきたいJavaScriptの基本知識
Vue.jsはJavaScriptフレームワークなので、JavaScriptの基礎知識は必須です。特に以下の概念は頻繁に利用します。
- 変数と定数 (
var
,let
,const
): データの保持。 - データ型: 文字列(string), 数値(number), 真偽値(boolean), 配列(array), オブジェクト(object) など。
- 関数: 処理のまとまり。アロー関数 (
() => {}
) もよく使われます。 - 配列とオブジェクトの操作: 配列のメソッド (
push
,pop
,map
,filter
,reduce
など) やオブジェクトのプロパティへのアクセス。 - DOM操作の概念: HTML要素の取得や変更といった直接的なDOM操作はVue.jsではほとんど行いませんが、「画面表示をJavaScriptで動的に変更する」という概念自体は重要です。Vue.jsはこれを宣言的に、効率的に行うためのツールです。
- ES Modules (import/export): CLIを使った開発では、JavaScriptファイルを分割し、必要な部分をインポート/エクスポートして使います。
これらの概念に不安がある方は、Vue.jsの学習と並行して、MDN Web DocsなどでJavaScriptの基礎を復習することをおすすめします。
Vue.jsの開発環境を構築する
Vue.jsの導入方法はいくつかありますが、ここでは代表的な二つの方法をご紹介します。
- CDN (Content Delivery Network) を使う方法: 最も手軽で、HTMLファイル一つからすぐに始められます。小規模な検証や、既存のプロジェクトに部分的にVue.jsを導入したい場合に便利です。
- Vue CLI (Vue 2) / create-vue (Vue 3) を使う方法: Vue.jsを使った本格的なアプリケーション開発ではこちらが推奨されます。開発に必要なツール(ビルドツール、ホットリロード、単一ファイルコンポーネントのコンパイルなど)があらかじめ設定されたプロジェクトを簡単に作成できます。
方法1: CDNで始める(最速導入)
CDNを使う方法は、Node.jsなどの環境構築が不要で、既存のHTMLファイルに<script>
タグを追加するだけでVue.jsを読み込めるため、最も手軽に Vue.js を試すことができます。
まずは簡単な「Hello, Vue!」を表示する例を見てみましょう。
以下の内容で index.html
ファイルを作成してください。
“`html
“`
このファイルをブラウザで開いてみてください。「Hello, Vue!」と表示されるはずです。
コードの説明:
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
:- これがVue.jsライブラリ本体をインターネット上から読み込むためのタグです。CDNを使うことで、自分のPCにVue.jsをダウンロード・インストールすることなく利用できます。
- ここではVue 3のCDNを使っています。Vue 2の場合はURLが異なります。
<div id="app"> {{ message }} </div>
:- これがVue.jsが制御する範囲を示す部分です。
id="app"
という要素を、後述するVueアプリケーションの「マウントポイント」として指定します。 {{ message }}
という波括弧で囲まれた部分は、Vue.jsのテンプレート構文です。ここで囲まれた部分は、Vueインスタンス(またはアプリケーションインスタンス)のdata
オプションで定義されたmessage
という名前のプロパティの値に置き換えられます。
- これがVue.jsが制御する範囲を示す部分です。
<script> ... </script>
内のJavaScriptコード:const app = Vue.createApp({...})
- Vue 3では、
Vue.createApp()
メソッドを使って新しいアプリケーションインスタンスを作成します。このメソッドに、アプリケーションの設定を記述したオプションオブジェクトを渡します。 - Vue 2では、
new Vue({...})
のようにVue
コンストラクタを使ってVueインスタンスを作成しました。
- Vue 3では、
data() { return { message: 'Hello, Vue!' } }
data
オプションは、アプリケーションが管理するデータを定義するために使用します。Vue 3では、data
は必ず関数として定義し、その関数がオブジェクトを返します。このオブジェクトのプロパティ(例:message
)が、テンプレートから参照できるようになり、またこれらのデータはリアクティブになります。リアクティブとは、データの値が変更されたときに、そのデータを表示している画面の部分が自動的に更新される仕組みです。
.mount('#app')
- 作成したVueアプリケーションインスタンスを、HTML上のどの要素に紐づけるか(マウントするか)を指定します。ここでは
#app
というIDを持つ要素(先ほどのdiv
)にマウントしています。Vueは、この要素とその子要素の範囲を制御するようになります。
- 作成したVueアプリケーションインスタンスを、HTML上のどの要素に紐づけるか(マウントするか)を指定します。ここでは
CDNを使った方法は非常に簡単ですが、本格的なアプリケーション開発には向いていません。その理由は、単一ファイルコンポーネントが使えない、ビルドプロセスがない(コードの最適化やトランスパイルができない)、依存関係の管理が難しい、といった点があるからです。
方法2: Vue CLI (Vue 2) / create-vue (Vue 3) で始める(推奨)
Vue.jsを使った本格的な開発では、公式のツールであるVue CLI (主にVue 2向け) または create-vue (主にVue 3向け、Viteベース) を使うのが一般的です。これらを使うことで、モダンな開発環境(ホットリロード、単一ファイルコンポーネント、ES Modules、PostCSS/SassなどのCSSプリプロセッサ、TypeScript、Linter/Formatterなど)がすぐに整います。
この方法を使うには、まず以下のものをインストールする必要があります。
-
Node.js: JavaScriptの実行環境です。サーバーサイドJavaScriptとして知られていますが、Vue.js開発では、プロジェクト管理やビルドツール実行のために使用します。Node.jsをインストールすると、パッケージマネージャーである npm (Node Package Manager) も一緒にインストールされます。npmは、Vue.js本体や関連ライブラリをプロジェクトにインストールするために使います。
- Node.jsの公式サイト (https://nodejs.org/) からLTS版(長期サポート版)をダウンロードしてインストールしてください。
- インストール後、ターミナルまたはコマンドプロンプトを開き、以下のコマンドを実行してバージョンが表示されることを確認してください。
bash
node -v
npm -v - npmの代わりに yarn や pnpm といった別のパッケージマネージャーを使うこともできます。今回はnpmを例に進めます。
-
Vue CLI (Vue 2 開発向け) または create-vue (Vue 3 開発向け):
- Vue CLI (Vue 2 メインの場合): グローバルにインストールします。
bash
npm install -g @vue/cli
インストール後、バージョン確認。
bash
vue --version - create-vue (Vue 3 メインの場合):
npm create vue@latest
のように、npm init
(またはyarn create
,pnpm create
) コマンドを使ってプロジェクト作成時に実行するのが一般的です。グローバルインストールは不要です。
- Vue CLI (Vue 2 メインの場合): グローバルにインストールします。
この記事では、最新のVue 3に対応しており、より高速な開発サーバーであるViteをベースにした create-vue を使った方法を推奨し、以降の説明もそちらをメインに進めます。(Vue CLIとcreate-vueではプロジェクト構成などが多少異なりますが、Vue.js本体の書き方に関する基本的な部分は共通です)
create-vue を使ってプロジェクトを作成する手順:
- プロジェクトを作成したいディレクトリに移動します。
- ターミナルを開き、以下のコマンドを実行します。
bash
npm create vue@latest -
いくつか質問されます。矢印キーで選択し、Enterキーで決定します。
Project name:
プロジェクト名を入力します。例:my-vue-app
Add TypeScript?
(y/n) TypeScriptを使いますか? 初心者のうちはn
で良いでしょう。Add JSX Support?
(y/n) JSXを使いますか? VueではJSXを使うことは稀なのでn
で良いでしょう。Add Vue Router for Single Page Application development?
(y/n) ルーティング(ページの切り替え)機能を追加しますか? 後からでも追加できるので、ここではn
で良いでしょう。Add Pinia for State Management?
(y/n) 状態管理ライブラリを追加しますか? 小規模アプリでは不要なのでn
で良いでしょう。Add Vitest for Unit Testing?
(y/n) 単体テストライブラリを追加しますか? 初心者のうちはn
で良いでしょう。Add Cypress for End-to-End Testing?
(y/n) E2Eテストライブラリを追加しますか? 初心者のうちはn
で良いでしょう。Add ESLint for code linting?
(y/n) コードの整形・検査ツールを追加しますか? コードの品質を保つために便利ですが、初心者には少し設定が煩雑な場合もあるので、ここではn
で良いでしょう。Add Prettier for code formatting?
(y/n) コード整形ツールを追加しますか? コードを自動できれいに整形してくれるので便利です。y
にしても良いでしょう。
例として、全て
n
またはデフォルトのまま進めた場合の例:
“`
Need to install the following packages:
create-vue@latest
Ok to proceed? (y) yVue.js – The Progressive JavaScript Framework
? Project name: my-vue-app
? Add TypeScript? (y/n) n
? Add JSX Support? (y/n) n
? Add Vue Router for Single Page Application development? (y/n) n
? Add Pinia for State Management? (y/n) n
? Add Vitest for Unit Testing? (y/n) n
? Add Cypress for End-to-End Testing? (y/n) n
? Add ESLint for code linting? (y/n) n
? Add Prettier for code formatting? (y/n) nScaffolding project in C:\path\to\your\directory\my-vue-app…
Done. Now run:
cd my-vue-app
npm install
npm run dev
4. 指示された通りに、作成されたプロジェクトディレクトリに移動し、依存関係をインストールします。
bash
cd my-vue-app
npm install
``
yarn install
(またはまたは
pnpm install`) -
開発サーバーを起動します。
bash
npm run dev
(またはyarn dev
またはpnpm dev
) -
ターミナルに表示されたURL (例:
http://localhost:5173/
) にブラウザでアクセスしてください。Vueのウェルカムページが表示されるはずです。
これで、CLIを使ったVue.js開発の準備が整いました!
プロジェクトのディレクトリ構成について(create-vueの場合)
作成されたプロジェクトディレクトリの中身を見てみましょう。
my-vue-app/
├── node_modules/ # プロジェクトの依存関係(ライブラリなど)
├── public/ # 静的ファイル(faviconなど)。ビルド時にそのまま出力される
├── src/ # ソースコード
│ ├── assets/ # 画像などのアセット
│ ├── components/ # 再利用可能なコンポーネントを置くディレクトリ
│ │ └── HelloWorld.vue # 例として作成されるコンポーネント
│ ├── App.vue # アプリケーションのルートコンポーネント
│ └── main.js # アプリケーションのエントリーポイント(最初に実行されるJavaScriptファイル)
├── .gitignore # Gitで無視するファイル・ディレクトリの設定
├── index.html # アプリケーションのベースとなるHTMLファイル
├── package.json # プロジェクトの情報、依存関係、スクリプトなどが記述されたファイル
└── vite.config.js # Viteの設定ファイル
package.json
: プロジェクトの「設計図」のようなものです。dependencies
には必要なライブラリ、scripts
にはnpm run dev
のようなコマンドが定義されています。index.html
: CDN版のHTMLと似ていますが、Vueアプリケーションをマウントするための要素(通常<div id="app"></div>
)と、アプリケーションのエントリーポイントとなるJavaScriptファイルを読み込む<script type="module" src="/src/main.js"></script>
があります。src/main.js
: アプリケーションの起点となるファイルです。ここでVueアプリケーションインスタンスを作成し、ルートコンポーネント (App.vue
) を読み込み、マウントします。src/App.vue
: アプリケーション全体のルートコンポーネントです。アプリケーションのレイアウトや、他のコンポーネントの配置を定義します。src/components/
: 小さな部品となるコンポーネントを配置するディレクトリです。
CLIで作成したプロジェクトでは、.vue
という拡張子を持つファイルを頻繁に使います。これは単一ファイルコンポーネント (Single File Component – SFC) と呼ばれるもので、1つのファイルの中にHTML (<template>
), JavaScript (<script>
), CSS (<style>
) をまとめて記述できます。これにより、コンポーネントごとに論理的に分割された、分かりやすく管理しやすいコードになります。CLIツールはこのSFCをブラウザが理解できるJavaScript, CSS, HTMLに変換(ビルド)してくれます。
以降の章では、主にCLIで作成したプロジェクト(Vue 3 + Vite)を前提に、Vue.jsの基本的な使い方を学習していきます。必要に応じてCDN版との違いにも触れます。
Vue.jsの基本を学ぶ
ここでは、Vue.jsでアプリケーションを構築するための基本的な概念や構文を学びます。CLIで作成したプロジェクトの src/App.vue
や新しくコンポーネントを作成してコードを書いていきましょう。
Vueアプリケーションインスタンスとリアクティビティ
Vue 3では createApp()
で作成するアプリケーションインスタンスが中心となります。このインスタンスに様々なオプションを設定することで、アプリケーションの振る舞いを定義します。
src/App.vue
を開いてみましょう。初期状態は以下のようになっているはずです(多少異なる場合があります)。
“`vue
“`
これはComposition API + <script setup>
というVue 3の推奨スタイルで書かれています。今回は初心者向けとして、従来の Options API を中心に説明を進めます。まずは App.vue
をOptions APIで書き直してみましょう。
“`vue
{{ message }}
“`
開発サーバー (npm run dev
) が起動している状態でこの変更を保存すると、ブラウザの表示が自動的に更新され、「Hello, Vue 3 with Options API!」という見出しとボタンが表示されているはずです。ボタンをクリックすると、見出しのテキストが「メッセージが変更されました!」に変わります。
これがVue.jsのリアクティビティです。data
オプションで定義した message
プロパティの値を methods
で定義した changeMessage
関数内で変更すると、その変更が自動的にテンプレートに反映されます。手動でDOM要素を取得してテキストを書き換える必要はありません。
Options APIでよく使う主なオプションを見てみましょう。
-
data
: コンポーネントのローカルなリアクティブ状態を定義します。Vue 3では関数として定義し、オブジェクトを返します。
javascript
data() {
return {
propertyName: '初期値',
anotherProperty: 123
}
}
テンプレートからはpropertyName
のように直接プロパティ名でアクセスできます。メソッド内からはthis.propertyName
のようにthis
キーワードを使ってアクセスします。 -
methods
: コンポーネントで使用する関数を定義します。イベントハンドリングや、特定の処理を実行したい場合に使います。
javascript
methods: {
myMethod() {
// データや他のメソッドにアクセス可能
this.propertyName = '新しい値';
this.anotherMethod();
},
anotherMethod() {
console.log('別のメソッドが実行されました');
}
}
テンプレートからは@event="myMethod"
のように、イベント名とメソッド名を指定して呼び出せます。 -
computed
: 依存するデータが変更されたときにのみ再計算される「算出プロパティ」を定義します。複数のデータから動的に計算される値を表示したい場合などに便利です。メソッドと似ていますが、computed
プロパティは値をキャッシュするため、依存データが変わらない限り何度参照されても再計算されません。
javascript
data() {
return {
firstName: '山田',
lastName: '太郎'
}
},
computed: {
fullName() {
// firstName または lastName が変更されると再計算される
return this.lastName + ' ' + this.firstName;
}
}
テンプレートからは{{ fullName }}
のように、データプロパティと同じように参照できます。 -
watch
: 特定のデータプロパティの変更を監視し、値が変わったときに任意の処理を実行したい場合に定義します。非同期処理やコストの高い処理を、特定のデータの変更に応じて実行したい場合に使います。
javascript
data() {
return {
question: '',
answer: '質問が終わるまで考えていません...'
}
},
watch: {
// question プロパティの変更を監視
question(newQuestion, oldQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer()
} else {
this.answer = '質問が終わるまで考えていません...'
}
}
},
methods: {
getAnswer() {
this.answer = '考えています...'
// ここで非同期処理(例: API呼び出し)を行う
setTimeout(() => {
this.answer = 'はい、そうです。' // 例として決め打ち
}, 1000)
}
}
watch
のハンドラ関数は、第一引数に新しい値、第二引数に古い値を受け取ります。 -
ライフサイクルフック: コンポーネントの生成、マウント、更新、破棄といったライフサイクルの特定の段階で実行される関数です。
created()
: インスタンスが作成された直後に実行されます。データがセットアップされ、イベントが構成された後ですが、まだDOMにはマウントされていません。データの初期化などによく使われます。mounted()
: インスタンスがDOMにマウントされた後(最初のレンダリングが完了した後)に実行されます。DOM要素にアクセスしたい場合や、サードパーティライブラリを初期化したい場合などに使われます。updated()
: データが変更され、DOMが更新された後に実行されます。unmounted()
: インスタンスが破棄される直前に実行されます。タイマーのクリアやイベントリスナーの削除など、クリーンアップ処理に使われます。
テンプレート構文
Vue.jsでは、HTMLベースのテンプレート構文を使用して、DOMをデータに宣言的にバインドします。
主なテンプレート構文:
-
テキスト展開
{{ }}
(Mustache構文):- データプロパティの値をテキストとして表示します。HTMLエスケープが自動的に行われるため、XSS攻撃のリスクを低減できます。
html
<p>メッセージ: {{ message }}</p>
<p>現在の数値: {{ count + 1 }}</p> <!-- 簡単なJavaScript式も使用可能 -->
- データプロパティの値をテキストとして表示します。HTMLエスケープが自動的に行われるため、XSS攻撃のリスクを低減できます。
-
HTML展開
v-html
:- 生のHTMLとして出力したい場合に属性として指定します。ただし、ユーザーからの入力をそのまま表示するとXSS攻撃のリスクがあるため、信頼できるコンテンツにのみ使用すべきです。
html
<div v-html="rawHtml"></div>
javascript
data() {
return {
rawHtml: '<span>これは<b>太字</b>のテキストです</span>'
}
}
- 生のHTMLとして出力したい場合に属性として指定します。ただし、ユーザーからの入力をそのまま表示するとXSS攻撃のリスクがあるため、信頼できるコンテンツにのみ使用すべきです。
-
属性バインディング
v-bind
(または:
)- HTML属性にデータプロパティの値をバインドします。
html
<img v-bind:src="imageUrl" alt="画像">
<a :href="linkUrl">リンク</a> <!-- v-bind: は : に省略可能 -->
<button :disabled="isButtonDisabled">送信</button>
クラスやスタイルを動的にバインディングすることも頻繁に行われます。
“`html
“`
- HTML属性にデータプロパティの値をバインドします。
-
イベントハンドリング
v-on
(または@
)- DOMイベント(クリック、入力など)をリッスンし、指定したJavaScriptコードを実行します。
html
<button v-on:click="handleClick">クリック</button>
<input @input="handleInput"> <!-- v-on: は @ に省略可能 -->
<form @submit.prevent="handleSubmit"></form> <!-- .prevent はイベント修飾子 -->
イベントハンドラには、メソッド名、インラインJavaScript式、または無名関数を指定できます。
html
<button @click="counter++">カウントアップ</button> <!-- インライン式 -->
<button @click="greet('Hello')">引数を渡す</button> <!-- メソッドに引数を渡す -->
イベント修飾子: イベントハンドラの末尾に付けることで、標準的なイベント処理を簡単に行えます。 .stop
:event.stopPropagation()
を呼び出します。(イベントの伝播を停止).prevent
:event.preventDefault()
を呼び出します。(デフォルトの動作を抑制).capture
: キャプチャフェーズでイベントリスナーを追加します。.self
: イベントが発生した要素自身でのみハンドラを実行します。.once
: イベントリスナーを一度だけ実行します。.passive
:prevent
を使わないことをブラウザに伝えます(スクロールパフォーマンス向上など)。
キー修飾子: キーボードイベント (
@keyup
,@keydown
など) で特定のキーが押されたときにのみハンドラを実行します。
*.enter
,.tab
,.delete
(Delete および Backspace),.esc
,.space
,.up
,.down
,.left
,.right
など。
html
<input @keyup.enter="submit"> <!-- Enterキーが押されたらsubmitメソッドを実行 -->
システム修飾子: マウスまたはキーボードイベントで、特定のシステムキー(Ctrl, Altなど)が押されているかを判定します。
*.ctrl
,.alt
,.shift
,.meta
(WindowsキーやCommandキー)
html
<div @click.ctrl="doSomething">Ctrlキーを押しながらクリック</div>
.exact
修飾子: 他のシステム修飾子なしで、指定された修飾子のみが押されている場合にトリガーされます。 - DOMイベント(クリック、入力など)をリッスンし、指定したJavaScriptコードを実行します。
条件付きレンダリング (v-if
, v-else-if
, v-else
, v-show
)
特定の条件に基づいて要素を表示したり非表示にしたりします。
-
v-if
,v-else-if
,v-else
:- 条件が真のときに要素をレンダリングします。偽の場合はDOMから完全に削除されます。
- 連続して使用することで、if/else if/else の条件分岐を実現できます。
html
<div v-if="type === 'A'">タイプA</div>
<div v-else-if="type === 'B'">タイプB</div>
<div v-else>その他のタイプ</div>
v-if
は<template>
要素と一緒に使うと、ラッパー要素なしで複数の要素を条件付きでレンダリングできます。
html
<template v-if="ok">
<h1>タイトル</h1>
<p>段落1</p>
<p>段落2</p>
</template>
v-if
は切り替えコストが高い(要素の生成・破棄)ため、頻繁に切り替わる場合はv-show
を検討します。
-
v-show
:- 条件が真のときに要素を表示します。偽の場合もDOMには要素が存在しますが、
display: none;
のスタイルが適用されて非表示になります。
html
<div v-show="isVisible">この要素は表示/非表示が切り替わります</div>
v-show
は初期レンダリングコストは高い(常にDOMを生成する)ですが、切り替えコストは低い(スタイル変更のみ)です。表示/非表示が頻繁に切り替わる場合はv-show
が適しています。
- 条件が真のときに要素を表示します。偽の場合もDOMには要素が存在しますが、
リストレンダリング (v-for
)
配列やオブジェクトの要素をリストとしてレンダリングします。
-
配列のリストレンダリング:
html
<ul>
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</ul>v-for="item in items"
:items
配列の各要素を順に取り出し、item
という名前で利用できるようにします。:key="item.id"
:v-for
を使う際は、各要素に一意の:key
属性を指定することが非常に重要です。Vueが要素の変更(追加、削除、並べ替え)を効率的に追跡し、仮想DOMの差分検知や要素の状態維持(例: 入力フィールドの値)を正しく行うために必要です。リスト内の各アイテムに安定したユニークなID(またはインデックスでも代用できますが、可能ならIDを)を割り当ててください。- インデックスも一緒に取得できます。
html
<ul>
<li v-for="(item, index) in items" :key="index">
{{ index }} - {{ item.text }}
</li>
</ul>
-
オブジェクトのリストレンダリング:
- オブジェクトのプロパティをループします。
html
<ul>
<li v-for="(value, key, index) in object" :key="key">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul> v-for="(value, key, index) in object"
: オブジェクトの各プロパティから、値 (value)、キー (key)、インデックス (index) を取得できます。
- オブジェクトのプロパティをループします。
-
範囲のリストレンダリング:
- 指定した回数だけ要素を繰り返します。
html
<span v-for="n in 10">{{ n }} </span> <!-- 1 から 10 までの数値を出力 -->
- 指定した回数だけ要素を繰り返します。
フォーム入力バインディング (v-model
)
フォーム要素(<input>
, <textarea>
, <select>
)とデータを双方向にバインディングします。フォームの入力値が変更されるとデータが更新され、データが更新されるとフォームの入力値も更新されます。
v-model
は、入力要素に対して v-bind:value
(または v-bind:checked
, v-bind:selected
) と v-on:input
(または v-on:change
) を組み合わせた糖衣構文(シンタックスシュガー)です。
-
テキスト入力、テキストエリア:
html
<input type="text" v-model="message">
<textarea v-model="message"></textarea>
<p>入力値: {{ message }}</p>
ユーザーが入力フィールドに何かを入力すると、message
データプロパティの値が自動的に更新されます。 -
チェックボックス:
- 単一のチェックボックス(真偽値):
html
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label> - 複数のチェックボックス(配列):同じ
v-model
で複数のチェックボックスをバインドし、value
属性を設定します。
html
<div>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
</div>
<p>選択された名前: {{ checkedNames }}</p>
javascript
data() {
return {
checkedNames: [] // 配列として初期化
}
}
- 単一のチェックボックス(真偽値):
-
ラジオボタン:
html
<div>
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
</div>
<p>選択されたラジオボタン: {{ picked }}</p>
javascript
data() {
return {
picked: '' // 文字列として初期化
}
} -
セレクトボックス:
- 単一選択:
html
<select v-model="selected">
<option disabled value="">選択してください</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>選択された項目: {{ selected }}</p>
javascript
data() {
return {
selected: ''
}
} - 複数選択 (
multiple
属性):
html
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>選択された項目: {{ selected }}</p>
javascript
data() {
return {
selected: [] // 配列として初期化
}
} option
の値を動的にバインドする場合:
html
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
javascript
data() {
return {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
}
- 単一選択:
-
v-model
修飾子:.lazy
:input
イベントではなくchange
イベントで同期します。テキスト入力中にデータが頻繁に更新されるのを抑えたい場合に便利です。.number
: 入力値を自動的に数値に型キャストします。.trim
: 入力値の先頭と末尾の空白を自動的に削除します。
コンポーネント
コンポーネントはVue.jsアプリケーションの重要な概念です。UIを再利用可能な独立した部品に分割することで、コードの管理が容易になり、開発効率が向上します。
CLIで作成したプロジェクトでは、単一ファイルコンポーネント (SFC) が標準です。.vue
ファイルとして、<template>
, <script>
, <style>
の3つのブロックで構成されます。
例: src/components/MyComponent.vue
“`vue
{{ title }}
このコンポーネントは {{ message }} と表示します。
“`
コンポーネントの利用方法:
作成したコンポーネントは、他のコンポーネント(親コンポーネント)の中で使用します。使うためには、まず親コンポーネントの <script>
ブロックでインポートし、components
オプションに登録します(ローカル登録)。
例: src/App.vue
で MyComponent.vue
を使う場合
“`vue
Vue.js コンポーネントの基本
子コンポーネントのカウンター合計: {{ totalCounter }}
“`
コードの説明:
import MyComponent from './components/MyComponent.vue'
:MyComponent.vue
ファイルをインポートしています。ES Modulesの構文です。components: { MyComponent }
: 親コンポーネントのcomponents
オプションにインポートしたMyComponent
を登録します。これにより、テンプレート内で<MyComponent>
というカスタム要素として使用できるようになります。キー名と値名が同じなので、{ MyComponent }
と省略できます。<MyComponent ... />
: テンプレート内でカスタム要素としてコンポーネントを使用します。- Props (親から子へのデータ渡し):
- 子コンポーネント (
MyComponent
) の<script>
ブロックでprops
オプションにtitle
とmessage
を定義しています。 - 親コンポーネント (
App.vue
) のテンプレートで<MyComponent>
タグに:title="..."
や:message="..."
という属性を指定することで、親のデータを子のPropsに渡せます。:attribute="value"
はv-bind:attribute="value"
の省略形であり、属性値がJavaScript式として評価されることを意味します。ここでは文字列リテラルを渡していますが、親のデータプロパティを渡すこともできます。
html
<MyComponent :title="parentTitleData" />
- 子コンポーネント (
- Custom Events (子から親への通知):
- 子コンポーネント (
MyComponent
) のincrementCounter
メソッド内でthis.$emit('counter-updated', this.counter)
を呼び出しています。$emit
は、親コンポーネントに対してカスタムイベントを発生させるためのメソッドです。第一引数にイベント名、第二引数以降にイベントに渡すデータを指定します。 - 親コンポーネント (
App.vue
) のテンプレートで<MyComponent>
タグに@counter-updated="handleCounterUpdate"
という属性を指定することで、子から発生したcounter-updated
イベントをリッスンし、親コンポーネントのhandleCounterUpdate
メソッドを実行できます。@event="method"
はv-on:event="method"
の省略形です。handleCounterUpdate
メソッドは、子から$emit
で渡されたデータ(カウンターの値)を引数として受け取ります。
- 子コンポーネント (
コンポーネントを使うことで、UIをより小さく、管理しやすい単位に分割し、再利用性を高めることができます。これはVue.js開発の最も基本的な、そして最も重要な考え方の一つです。
スロット (Slots)
スロットは、コンポーネントのテンプレート内に、親コンポーネントが提供するコンテンツを挿入するための仕組みです。これにより、コンポーネントをより柔軟に、再利用可能にすることができます。
例: ボタンの中に任意のテキストを入れる MyButton.vue
“`vue
“`
親コンポーネントでの利用:
“`vue
“`
<slot>
タグがプレースホルダーとなり、親コンポーネントの <MyButton>
タグの間に記述されたコンテンツがそこに挿入されます。<slot>
タグの中に記述されたコンテンツは、親から何もコンテンツが渡されなかった場合のデフォルトコンテンツです。
スロットには、名前付きスロットやスコープ付きスロットといったより高度な機能もありますが、基本的な使い方は上記のとおりです。
簡単なアプリケーションを作ってみよう:Todoリスト
これまでに学んだVue.jsの基本的な概念や構文を使って、簡単なTodoリストアプリケーションを作成してみましょう。これにより、実際の開発の流れを体験できます。
作成するTodoリストの機能:
- 新しいタスクを追加できる。
- タスクの一覧を表示できる。
- 各タスクの完了状態を切り替えられる。
- 各タスクを削除できる。
CLI (create-vue
) で作成したプロジェクトを基に進めます。初期状態の src/App.vue
と src/components/HelloWorld.vue
などは削除またはコメントアウトして、Todoリストの実装に集中できるようにしましょう。
1. データ構造を考える
Todoリストに必要なデータは何でしょうか?
- タスクのリスト
- 各タスクには、「タスクの内容(テキスト)」と「完了しているかどうかの状態(真偽値)」が必要です。
- 各タスクを一意に識別するためのIDもあると、管理しやすくなります(特に削除や更新時)。
これらの要素を持つオブジェクトの配列としてデータを管理するのが良さそうです。
javascript
[
{ id: 1, text: '牛乳を買う', completed: false },
{ id: 2, text: 'Vue.jsを学ぶ', completed: true },
{ id: 3, text: '部屋を掃除する', completed: false }
]
2. ルートコンポーネント (App.vue
) の実装
まず、アプリケーション全体のコンポーネントである src/App.vue
を実装します。ここでタスクのデータ (todos
配列) を管理し、新しいタスクを追加する機能を作ります。
“`vue
Todoリスト
-
{{ todo.text }}
“`
npm run dev
で開発サーバーを起動し、ブラウザで確認してみましょう。タスクの追加、完了チェック、削除ができるようになっているはずです。
コードの説明:
data
:todos
: Todoオブジェクトの配列です。初期状態は空の配列です。newTodoText
: 新しいタスクを入力する<input>
要素とv-model
でバインディングされます。nextTodoId
: 新しいタスクに一意のIDを割り当てるためのカウンターです。
methods
:addTodo
:- フォームの
@submit.prevent
イベントで呼び出されます。.prevent
修飾子により、フォームのデフォルトの送信動作(ページリロード)を防ぎます。 this.newTodoText
が空でないかチェックします。this.todos.push(...)
で新しいTodoオブジェクトを配列の末尾に追加します。オブジェクトはnextTodoId
を使ってIDを生成し、text
は入力値、completed
はfalse
で初期化します。nextTodoId
をインクリメントします。this.newTodoText = ''
で入力フィールドをクリアします。
- フォームの
removeTodo
:- 削除ボタンの
@click
イベントで呼び出され、削除したいTodoのIDが引数として渡されます。 this.todos.filter(...)
を使って、引数で渡されたIDと異なるIDを持つTodoのみを抽出し、新しい配列としてthis.todos
に再代入します。Vue.jsのリアクティビティシステムは、配列の変更を検知して表示を更新します。
- 削除ボタンの
- テンプレート:
- フォーム要素に
@submit.prevent="addTodo"
を指定し、送信イベントをaddTodo
メソッドにバインディングしています。 - 入力フィールドに
v-model="newTodoText"
を指定し、入力値とnewTodoText
データを双方向バインディングしています。 <ul>
要素内でv-for="todo in todos"
を使い、todos
配列の各要素をループして<li>
要素として表示しています。:key="todo.id"
で一意のキーを指定しています。- 各
<li>
内で、チェックボックスにv-model="todo.completed"
を指定し、Todoオブジェクトのcompleted
プロパティとバインディングしています。 - タスクのテキストを囲む
<span>
に:class="{ completed: todo.completed }"
を指定し、todo.completed
がtrue
の場合にcompleted
クラスが付与されるようにしています。これにより、CSSで完了したタスクにスタイルを適用できます。 - 削除ボタンに
@click="removeTodo(todo.id)"
を指定し、クリックイベントをremoveTodo
メソッドにバインディングし、引数としてそのTodoのIDを渡しています。
- フォーム要素に
このコードは、Todoリストの基本的な機能を持っています。しかし、全ての要素をルートコンポーネントに詰め込むと、コードが長くなり、管理が難しくなります。特にリスト表示部分は、一つのTodoアイテムに対する表示や操作(完了チェック、削除)のロジックを含んでおり、これを部品として分割したいと考えられます。
3. 子コンポーネントへの分割
Todoアイテム一つ一つを表示・管理する部分を、TodoItem.vue
という子コンポーネントに分割してみましょう。
まず、src/components
ディレクトリ内に TodoItem.vue
ファイルを作成します。
“`vue
{{ todo.text }}
“`
次に、src/App.vue
を更新して、TodoItem.vue
コンポーネントを使用するようにします。
“`vue
Todoリスト
@remove=”removeTodo”
@update-completed=”updateTodoCompleted”
/>
“`
変更を保存してブラウザを確認すると、見た目や動作は変わりませんが、コード構造が改善されました。
コードの説明:
TodoItem.vue
:- 親から
todo
という名前でTodoオブジェクトをPropsとして受け取ります。 - チェックボックスの
checked
属性をPropsのtodo.completed
にバインドしています。v-model
を使わずに:checked
と@change
を明示的に使っているのは、Propsは子コンポーネント内で直接変更すべきではない(「一方向データフロー」)というVueの原則に従うためです。子の変更を親に伝えるには、イベントを使います。 - チェックボックスの
@change
イベントで$emit('update-completed', todo.id, $event.target.checked)
を呼び出し、このTodoのIDと新しい完了ステータスを親に通知しています。 - 削除ボタンの
@click
イベントで$emit('remove', todo.id)
を呼び出し、このTodoのIDを親に通知しています。 - スタイルは
scoped
属性を付けて、このコンポーネント内のみに適用されるようにしています。
- 親から
App.vue
:TodoItem
コンポーネントをインポートし、components
オプションに登録しています。v-for
の中で<TodoItem>
コンポーネントを使用しています。:todo="todo"
で、ループ中の各todo
オブジェクトを、TodoItem
のtodo
Propsに渡しています。@remove="removeTodo"
で、TodoItem
からremove
イベントが発生したら、App.vue
のremoveTodo
メソッドを呼び出すようにしています。TodoItem
の$emit('remove', todo.id)
で渡されたtodo.id
は、removeTodo
メソッドの第一引数として受け取られます。@update-completed="updateTodoCompleted"
で、TodoItem
からupdate-completed
イベントが発生したら、App.vue
のupdateTodoCompleted
メソッドを呼び出すようにしています。TodoItem
の$emit('update-completed', todo.id, $event.target.checked)
で渡されたデータは、updateTodoCompleted
メソッドの引数として受け取られます。
このようにコンポーネントに分割することで、App.vue
は全体のデータの管理と、子コンポーネントへのデータの受け渡し・イベントのハンドリングに責任を持ち、TodoItem.vue
は個々のTodoアイテムの表示と、自身に対する操作イベントを親に通知することに責任を持つ、という役割分担が明確になり、コードの見通しが良くなります。
これで、基本的なTodoリストアプリケーションの実装が完了しました!
さらに学ぶために:Vue.js学習の次のステップ
この記事では、Vue.jsの基本的な使い方と開発環境構築、簡単なアプリケーション作成までをカバーしました。しかし、Vue.jsにはまだまだ多くの機能や、本格的なアプリケーション開発に必須となるエコシステム(関連ライブラリ)があります。
Vue.jsの学習をさらに深めるための次のステップをご紹介します。
- 公式ドキュメントを熟読する: Vue.jsの公式ドキュメント(日本語版あり)は非常に詳細で分かりやすいです。この記事で触れられなかった高度な機能や、今回学んだ機能についてもさらに深く理解するために、ぜひ活用してください。
- Vue.js 公式ドキュメント: https://ja.vuejs.org/
- Vue Router: SPA(シングルページアプリケーション)開発には必須のライブラリです。ブラウザのURLとVueコンポーネントを紐付けて、ページ遷移のような機能を実現します。
- Vue Router 公式ドキュメント: https://router.vuejs.org/ja/
- Pinia / Vuex (状態管理): アプリケーションの規模が大きくなると、コンポーネント間のデータ共有や状態管理が複雑になります。Pinia (Vue 3推奨) または Vuex (Vue 2) は、アプリケーション全体で共有する状態を一元管理するためのライブラリです。
- Pinia 公式ドキュメント: https://pinia.vuejs.org/
- Vuex 公式ドキュメント: https://vuex.vuejs.org/ja/
- Composition API (Vue 3): Options APIと並ぶVue 3の新しいAPIスタイルです。論理的な関連性に基づいてコードを整理しやすく、大規模コンポーネントやロジックの再利用においてOptions APIよりも優れている場合があります。モダンなVue 3開発では主流になりつつあります。
- Composition API (公式ドキュメント): https://ja.vuejs.org/guide/composition-api/introduction.html
- TypeScript: JavaScriptに静的型付けを導入する言語です。大規模プロジェクトでのコードの品質向上やメンテナンス性向上に役立ちます。Vue.jsプロジェクトでもTypeScriptを導入することが一般的になってきています。
- Vue + TypeScript (公式ドキュメント): https://ja.vuejs.org/guide/typescript/overview.html
- テスト: アプリケーションの品質を保証するためにテストは重要です。Vue Test Utilsを使ったコンポーネントの単体テストや、Cypress/Playwrightを使ったE2Eテストなどがあります。
- デプロイ: 作成したアプリケーションをインターネット上に公開する方法を学びます。Viteでビルドした静的ファイルを、Netlify, Vercel, GitHub Pages などの静的サイトホスティングサービスにデプロイするのが簡単です。
- その他のエコシステム: アニメーション (
<Transition>
)、Web Components、レンダリング関数、プラグイン作成など、さらに高度なトピックもたくさんあります。 - コミュニティに参加する: Vue.jsの公式DiscordサーバーやQiita、Zennなどの技術ブログ、Stack Overflowなどで質問したり、他の開発者の知見を学ぶのも良い方法です。
まとめ:Vue.js学習の旅は始まったばかり!
この記事では、Vue.jsとは何かという基本的な説明から始まり、CDNを使った最速導入、CLIを使った本格的な開発環境構築、そしてVue.jsの最も基本的な概念や構文(データ、メソッド、算出プロパティ、監視プロパティ、テンプレート構文、条件付きレンダリング、リストレンダリング、フォームバインディング、コンポーネント)を学びました。最後に、これらの知識を使って簡単なTodoリストアプリケーションを段階的に作成しました。
Vue.jsは、その学習のしやすさと柔軟性から、個人開発からエンタープライズ開発まで幅広く利用されています。この記事が、あなたがVue.jsでのWeb開発の第一歩を踏み出すための一助となれば幸いです。
新しい技術を学ぶのは時に大変ですが、Vue.jsは楽しく、そして強力なツールです。ぜひ、実際に手を動かしながら、色々な機能を試してみてください。エラーが出ても諦めずに、エラーメッセージをよく読み、検索して解決策を探しましょう。それは開発者にとって非常に重要なスキルです。
あなたのVue.js学習の旅は今始まったばかりです!これからも学び続け、素晴らしいWebアプリケーションをたくさん作り出してください。応援しています!