Vue.jsのcreatedフックとは?使い方を初心者向けに完全解説
はじめに
Vue.jsは、その学習のしやすさと強力な機能から、世界中のWeb開発者に愛されているJavaScriptフレームワークです。コンポーネントベースのアーキテクチャを採用しており、UIを再利用可能な部品として構築していくことができます。
Vue.jsを学び始めると、dataやmethods、computedといった基本的なオプションにはすぐに慣れるかもしれません。しかし、一歩進んでより動的で本格的なアプリケーションを構築しようとすると、必ず「ライフサイクルフック」という概念に直面します。
ライフサイクルフックは、Vueコンポーネントが「生まれてから消えるまで」の特定のタイミングで、決まった処理を実行するための仕組みです。これらを使いこなすことは、Vue.jsマスターへの重要なステップと言えるでしょう。
数あるライフサイクルフックの中でも、特に使用頻度が高く、初心者が最初に学ぶべき重要なフックがcreatedフックです。
この記事では、以下の内容を通じて、Vue.jsのcreatedフックを徹底的に、そして誰にでも分かるように解説していきます。
- Vue.jsのライフサイクル全体の流れ
createdフックの正確な役割とタイミングcreatedフックの具体的な使い方(API通信など)- 最も混同しやすい
mountedフックとの明確な違い - Composition APIでの
createdフックの扱い方 createdフックを使う上での注意点とベストプラクティス
この記事を読み終える頃には、あなたはcreatedフックを「いつ」「なぜ」「どのように」使うべきかを完全に理解し、自信を持って自分のアプリケーションに組み込めるようになっているはずです。Vue.jsの世界へ、さらに深く踏み込んでいきましょう!
第1章: Vue.jsのライフサイクルとは? — コンポーネントの「一生」を理解する
createdフックを理解するためには、まずその親概念である「ライフサイクル」について知る必要があります。
ライフサイクルとは?
Vueのコンポーネント(Vueインスタンス)は、Webページに表示されてから消えるまでの一連の過程をたどります。これを「ライフサイクル」と呼びます。人間が生まれて(誕生)、成長し(成人)、やがて役目を終える(死去)のと同じように、Vueコンポーネントにも「一生」があるのです。
- 生成 (Creation): コンポーネントがメモリ上に作られ、準備を始めます。
- マウント (Mounting): コンポーネントが実際のDOM(Webページの表示要素)に関連付けられ、画面に表示されます。
- 更新 (Updating): コンポーネント内のデータが変更され、表示が再描画されます。
- 破棄 (Unmounting): コンポーネントがDOMから取り除かれ、メモリから解放されます。
ライフサイクルフックとは?
「ライフサイクルフック」とは、このライフサイクルの特定の「節目」で自動的に呼び出される、私たちが定義できる関数のことです。
例えば、「コンポーネントが生成された直後」「画面に表示された直後」「データが更新される直前」といったタイミングで、特定のJavaScriptコードを実行したい場合に非常に役立ちます。
これにより、私たちは適切なタイミングで以下のような処理を正確に実行できます。
- サーバーからデータを取得する (API通信)
- DOMを直接操作する
- イベントリスナーを追加・削除する
- タイマー(
setIntervalなど)を開始・停止する
Vueライフサイクルの全体像
Vueの公式ドキュメントには詳細なライフサイクル図がありますが、ここでは初心者向けに主要なフックを簡略化してご紹介します。
(コンポーネントの旅)
↓
[ new Vue() ]
↓
【生成フェーズ】
- beforeCreate (準備開始前)
- created (準備完了! ★今回の主役)
↓
【マウントフェーズ】
- beforeMount (画面表示直前)
- mounted (画面表示完了!)
↓
【更新フェーズ (データ変更時に発生)】
- beforeUpdate (再描画直前)
- updated (再描画完了)
↓
【破棄フェーズ】
- beforeUnmount (お片付け直前)
- unmounted (お片付け完了)
この図を見てください。createdは「生成フェーズ」の最後に位置しています。これが非常に重要なポイントです。次の章で、このcreatedフックの役割を詳しく見ていきましょう。
第2章: createdフックとは? — 「準備完了」の合図
createdフックが実行されるタイミング
createdフックは、その名の通り「コンポーネントが作成された (created) 後」に実行されます。
より正確に言うと、Vueインスタンスが以下の初期化処理をすべて完了した直後に呼び出されます。
- リアクティブデータ (
data) の設定 - 算出プロパティ (
computed) の設定 - メソッド (
methods) の設定 - ウォッチャ (
watch) の設定
つまり、createdフックが実行される時点では、コンポーネントの「頭脳」にあたる部分はすべて準備万端の状態になっています。this.messageのようにしてdataのプロパティにアクセスしたり、this.myMethod()のようにしてmethodsで定義した関数を呼び出したりできます。
createdフックで「できること」と「できないこと」
このタイミングの特性から、createdフックでできること・できないことが明確に分かれます。
✅ できること
- リアクティブデータ (
dataやprops) へのアクセスと操作:
this.count++のように、コンポーネントのデータを自由に読み書きできます。 - API通信 (非同期処理):
サーバーから初期データを取得するのに最適な場所です。なぜなら、画面表示(マウント)を待たずに、できるだけ早くデータ取得処理を開始できるからです。 - イベントの購読やタイマーの設定:
setIntervalを開始したり、イベントバスのリスナーを設定したりといった、DOMに依存しない初期化処理を行えます。
❌ できないこと
- DOMへのアクセス:
createdフックが実行される時点では、コンポーネントはまだDOMにマウントされていません。つまり、画面上にはまだ存在しないのです。そのため、document.getElementById()のようなDOM操作や、Vueインスタンスが管理するDOM要素を指すthis.$elへのアクセスはできません。this.$elはundefinedになります。
beforeCreateフックとの比較で理解を深める
createdフックをより深く理解するために、その直前に実行されるbeforeCreateフックと比較してみましょう。
beforeCreate: データやメソッドの初期化が始まる前に呼ばれます。created: データやメソッドの初期化が完了した後に呼ばれます。
以下のコードを実行すると、その違いが一目瞭然です。
“`vue
“`
コンソールの出力結果:
--- beforeCreate フック ---
message: undefined
この時点では data や methods は未設定です。
--- created フック ---
message: こんにちは、Vue!
挨拶メソッドが呼ばれました。
この時点では data や methods にアクセスできます!
この結果からわかるように、beforeCreateの段階ではコンポーネントはまだ「空っぽ」ですが、createdの段階ではデータやメソッドがセットアップされ、利用可能な状態になっています。
この「データやメソッドは使えるが、DOMにはアクセスできない」という特性が、createdフックの役割を決定づけているのです。
第3章: createdフックの具体的な使い方 (実践編)
それでは、実際にcreatedフックをどのようにコードに記述し、活用していくのかを具体的なユースケースと共に見ていきましょう。
基本的な構文 (Options API vs Composition API)
Vueにはコンポーネントを記述する方法が2つあります。伝統的なOptions APIと、よりモダンなComposition APIです。それぞれでのcreatedフックの書き方を見てみましょう。
1. Options APIでの書き方
初心者が最初に触れることが多いのが、このOptions APIです。export default {} オブジェクトの中に、dataやmethodsと並列にcreatedメソッドを定義します。
“`javascript
// MyComponent.vue
export default {
data() {
return {
message: ‘初期メッセージ’
}
},
methods: {
// …メソッド定義
},
// ここに created フックを記述
created() {
// この中のコードが、コンポーネント作成時に実行される
console.log(‘コンポーネントが作成されました。’);
console.log(‘現在のメッセージ:’, this.message);
// データの内容を書き換えることも可能
this.message = 'createdフックでメッセージが変更されました!';
}
}
“`
2. Composition API (<script setup>) での書き方
Vue 3で導入されたComposition API、特に<script setup>構文を使う場合、明示的なcreatedフックは存在しません。
その代わりに、<script setup>ブロックのトップレベルに直接書かれたコードが、Options APIのcreatedフックとほぼ同じタイミングで実行されます。これは、setup関数がコンポーネントのプロパティやデータが解決された後に実行されるためです。
“`vue
“`
Composition APIの方がコードがシンプルになり、関連するロジックをまとめやすいという利点があります。この記事では主にOptions APIを中心に解説しますが、Composition APIでも同じ考え方が適用できることを覚えておいてください。
ユースケース1: APIからデータを取得する(最も重要な使い方)
createdフックの最も一般的で重要なユースケースは、外部APIからデータを取得し、コンポーネントのdataにセットすることです。
なぜcreatedが最適なのでしょうか?
それは、画面表示(マウント)を待たずにデータ取得を始められるため、ユーザーがデータを目にするまでの時間を少しでも短縮できるからです。
ここでは、axiosという人気のHTTPクライアントライブラリを使って、ユーザーリストを取得する例を見てみましょう。(axiosは別途インストールが必要です: npm install axios)
“`vue
ユーザーリスト
- {{ user.name }} ({{ user.email }})
“`
このコードのポイント:
dataオプションで、users(データ格納用)、isLoading(ローディング表示用)、error(エラー表示用)の3つの変数を初期化しています。createdフック内で、fetchUsersメソッドを呼び出しています。コンポーネントが作成されるとすぐにデータ取得が開始されます。fetchUsersメソッドはasync/awaitを使って非同期処理を記述しています。これにより、APIからの応答を待ってから次の処理に進むことができます。try...catch...finallyブロックを使って、成功時、失敗時、そして処理完了時のロジックを明確に分けています。これは堅牢なアプリケーションを作る上で非常に重要です。- テンプレート側では
v-if,v-else-if,v-elseを使って、isLoadingとerrorの状態に応じて表示を切り替えています。
このようにcreatedフックを活用することで、コンポーнентの初期化ロジックをきれいに分離し、効率的なデータ取得を実現できます。
ユースケース2: DOMに依存しない初期化処理
createdフックは、DOM要素を必要としない初期設定にも適しています。
例えば、コンポーネントが作成された時刻を記録したり、特定の処理を定期的に実行するためのタイマー(setInterval)を開始したりするケースです。
“`vue
このコンポーネントが作成されてから {{ secondsPassed }} 秒が経過しました。
“`
このコードの重要ポイント:
createdでsetIntervalのような処理を開始した場合、コンポーネントが不要になったときに必ずその処理を停止しなければなりません。さもないと、コンポーネントがページから消えてもタイマーはバックグラウンドで動き続け、メモリリークや意図しない動作の原因となります。
この「お片付け」処理を行うのが、beforeUnmount(またはunmounted)フックです。createdとunmountedは、初期化とクリーンアップのペアとして考える習慣をつけましょう。
第4章: createdと他のライフサイクルフックの比較
createdフックの役割をより明確にするために、他の重要なフック、特にmountedと比較してみましょう。これは初心者が最もつまずきやすいポイントです。
created vs mounted — 最大のライバル
mountedフックは、コンポーネントがDOMにマウントされ、画面に表示された直後に呼び出されます。
| フック | タイミング | DOMアクセス | 主な用途 |
|---|---|---|---|
created |
データ初期化後、DOM生成前 | 不可 ❌ | API通信、非同期処理の開始、DOMに依存しない初期化 |
mounted |
DOM生成後、画面表示完了 | 可能 ✅ | DOM要素の操作、DOMに依存するライブラリの初期化 |
この違いを体感するために、以下のコードを見てみましょう。
“`vue
“`
コンソールの出力結果:
--- created フック ---
this.$el: undefined
--- mounted フック ---
this.$el: <div>mountedフックで書き換えました!</div>
画面上の表示:
(青色で) mountedフックで書き換えました!
この結果がすべてを物語っています。
createdの時点ではthis.$el(コンポーネントのルートDOM要素)はundefinedです。コンポーネントはまだメモリ上に存在するだけで、画面には描画されていません。mountedの時点ではthis.$elは実際のHTML要素を指しており、JavaScriptで色を変えたりテキストを書き換えたりといったDOM操作が可能です。
どちらを使うべきか?フローチャートで判断!
処理をcreatedとmountedのどちらに書くか迷ったときは、以下の質問を自問自答してみてください。
-
その処理は、DOM要素に直接アクセスする必要があるか?
- YES →
mountedを使う。- 例: 特定の要素のサイズを取得したい、グラフ描画ライブラリを初期化したい、
document.addEventListenerを使いたい。
- 例: 特定の要素のサイズを取得したい、グラフ描画ライブラリを初期化したい、
- NO → 次の質問へ。
- YES →
-
その処理は、コンポーネントの初期データとして何かを取得・設定するものか?
- YES →
createdを使う。(またはComposition APIのsetup)- 例: APIから記事一覧を取得する、URLのクエリパラメータを読み取って
dataにセットする。
- 例: APIから記事一覧を取得する、URLのクエリパラメータを読み取って
- NO → その処理の目的に応じて他のフックや
methodsなどを検討する。
- YES →
API通信はどちらでも技術的には可能ですが、createdが推奨されるのは、前述の通り、マウントを待つ必要がなく、少しでも早く通信を開始してユーザー体験を向上させるためです。
created vs setup (Composition API)
Composition APIを使っている場合、setup関数(または<script setup>)がbeforeCreateとcreatedの役割を担います。
setupはpropsが解決された直後、コンポーネントインスタンスが作成される前に実行されます。setup内で宣言されたリアクティブなデータ(refやreactive)は、すぐに利用可能になります。
したがって、Options APIのcreatedで行っていた処理は、Composition APIではsetupの中に直接記述することになります。
Options API:
javascript
export default {
data() { return { posts: [] }; },
created() {
fetch('...')
.then(res => res.json())
.then(data => { this.posts = data; });
}
}
Composition API (<script setup>):
“`vue
``await`が使えるため、非同期の初期化処理をより直感的に書くことができます。
さらに、Composition APIではトップレベルで
“`vue
“`
この簡潔さはComposition APIの大きな魅力の一つです。
第5章: createdフックを使う上での注意点とベストプラクティス
createdフックを効果的に使うために、いくつか知っておくべき注意点があります。
1. 非同期処理とasync/await
createdフック自体を非同期関数にすることができます。これにより、フック内でawaitが使えるようになり、API通信などのコードが非常に読みやすくなります。
javascript
export default {
data() {
return {
user: null
}
},
// createdフックに`async`キーワードを付ける
async created() {
try {
console.log('非同期createdフックを開始します。');
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
this.user = await response.json();
console.log('ユーザーデータを取得しました:', this.user.name);
} catch (e) {
console.error('エラー:', e);
}
}
}
注意点: async created() を使ったとしても、Vueはcreatedフック内の非同期処理が完了するのを待たずに、マウント処理へと進みます。つまり、API通信が終わる前にコンポーネントが画面に表示される可能性があります。だからこそ、先ほどの例で見たようなv-if="isLoading"といったローディング状態の管理が重要になるのです。
2. サーバーサイドレンダリング (SSR) との関連
createdフックは、Nuxt.jsのようなフレームワークでサーバーサイドレンダリング(SSR)を行う際に非常に重要です。
createdフック: サーバーサイドとクライアントサイドの両方で実行されます。mountedフック: クライアントサイド(ブラウザ)でのみ実行されます。
この違いにより、SSR環境では、createdフック内でAPI通信を行うことで、サーバー側でデータを取得し、完全にレンダリングされたHTMLをクライアントに返すことができます。これにより、初期表示が高速化され、SEOにも有利になります。
もしmountedでAPI通信を行うと、サーバー側ではデータがない空の状態でHTMLが生成され、クライアント側で再度API通信が走ることになり、SSRの利点を活かせません。
(SSRは高度なトピックですが、createdがサーバーでも動くフックであることは覚えておくと良いでしょう。)
3. アロー関数を使わない
Options APIでcreatedフックを定義するとき、アロー関数 () => {} を使うべきではありません。
“`javascript
export default {
data() {
return { message: ‘Hello’ };
},
// 悪い例: アロー関数を使う
created: () => {
// この中の this は Vue インスタンスを指さない!
console.log(this.message); // -> undefined or error
},
// 良い例: 通常の関数 or メソッド記法を使う
created() {
// この中の this は正しく Vue インスタンスを指す
console.log(this.message); // -> ‘Hello’
}
}
``this
アロー関数は自身のを持たず、外側のスコープのthisを参照します。そのため、createdでアロー関数を使うと、thisが期待通りにVueインスタンスを指さなくなり、dataやmethodsにアクセスできなくなってしまいます。必ず通常の関数function() {}またはメソッド記法created() {}` を使いましょう。
第6章: よくある質問 (FAQ)
Q1: createdでAPI通信のコードを書きましたが、画面にデータが表示されません。なぜですか?
A1: 最もよくある原因は2つです。
1. 非同期処理の理解不足: fetchやaxiosは非同期で実行されます。APIからデータが返ってくる前に画面が描画されるため、初期値(例: 空の配列 [])が表示されている可能性があります。v-ifでローディング状態を管理し、データが取得できているかconsole.logで確認しましょう。
2. リアクティブデータへの代入忘れ: APIから取得したデータを、this.users = response.data; のように、dataオプションで定義したリアクティブな変数に正しく代入していますか? ただ取得するだけでは、Vueはデータの変更を検知できず、画面を更新してくれません。
Q2: Composition APIを使っています。createdはどこに書けばいいですか?
A2: <script setup>を使っている場合、createdに相当する明示的なフックはありません。<script setup>タグの直下に書かれたコードがcreatedと同じタイミングで実行されるので、そこに初期化処理を直接記述してください。
Q3: ページ遷移してもcreatedフックが一度しか実行されません。
A3: Vue Routerを使っている場合、<router-view>に表示されるコンポーネントは、デフォルトで再利用されることがあります(特にルートのパラメータだけが変わる場合など)。そのため、createdフックは最初の表示時にしか呼ばれません。
もし、URLが変わるたびにデータを再取得したい場合は、watchフックでルートの変更($route)を監視するか、beforeRouteUpdateというナビゲーションガードを使うのが一般的な解決策です。
まとめ
この記事では、Vue.jsのcreatedライフサイクルフックについて、その基本から実践的な使い方、注意点までを詳しく解説しました。最後に、重要なポイントを振り返りましょう。
- ライフサイクルとは、Vueコンポーネントが生成されてから破棄されるまでの一連の流れです。
- ライフサイクルフックとは、その流れの特定のタイミングで処理を実行するための「割り込み」機能です。
createdフックは、コンポーネントのdataやmethodsなどが初期化された直後、しかしDOMが生成される前に実行されます。createdでできることの代表は、API通信による初期データの取得や、DOMに依存しない初期化処理です。createdでできないことは、DOMへのアクセスです。this.$elは使えません。- DOM操作が必要な場合は、DOM生成後に実行される
mountedフックを使います。 - Composition API (
<script setup>) では、トップレベルのコードがcreatedの役割を果たします。 createdでタイマーなどを設定した場合は、メモリリークを防ぐためにbeforeUnmountで必ずクリーンアップ処理を行いましょう。
createdフックは、Vue.jsアプリケーションに命を吹き込み、外部の世界(APIサーバーなど)と接続するための最初の扉です。このフックを正しく理解し、mountedなどの他のフックと適切に使い分けることで、あなたのVue.jsスキルは格段に向上するでしょう。
さあ、今日学んだことを活かして、あなたのコンポーネントに素晴らしい初期化処理を実装してみてください!