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スキルは格段に向上するでしょう。
さあ、今日学んだことを活かして、あなたのコンポーネントに素晴らしい初期化処理を実装してみてください!