vue.jsを学び始めるとvue.jsのライフサイクルの説明を目にする機会が増えてきます。私がそうであったようにvue.jsを含めJavaScriptのフレームワークに触れたことがない人にとってはライフサイクルというものが何なのか理解するのが最初は非常に難しいです。最初はすべてを理解しようとせず利用頻度の高いcreated, mountedで何が行われるのかと2つの区別がはっきりつけばライフサイクルの理解が進むかもしれません。本文書ではvue.jsのライフライクルフックcreatedとmountedの違いを要素elを使って説明していきます。

vue.jsはcdnを利用して使うため特別な環境の構築は必要ありません。デスクトップ等にindex.htmlファイルを作成し一緒に動作確認を行なってみてください。

下記はvue.jsの公式サイトに掲載されているライフサイクル図です。今回はこの図の中でelとライフサイクルフックcreated, mountedさらにbeforeCreateの3つのみ注目します。

vue.jsライフサイクル
vue.jsライフサイクル

ライフサイクルフックとは

created, mountedはライフサイクルフックと呼ばれ、vue.jsの初期化の中の決められたタイミングで実行される関数です。各ライフサイクルフックの中にプログラムを記述することでvue.jsの初期化の流れの中で記述したプログラムを必ず実行させることができます。

初期化とはvue.jsが使えるようになるまでのvue.jsの内部で行われる処理のことです。WindowsやMac OSが起動するときにユーザが利用できるまで少し時間がかかります。Vue.jsでも同様にユーザが利用できるまでにさまざまな処理が行われます。

APIなどを利用して外部からデータを取得してブラウザに表示させたい場合は、ライフサイクルフックの中に外部からデータを取得できるaxios、fetchを利用してデータ取得のプログラムを記述しておきます。ライフサイクルフックの中にデータ取得のプログラムを記述することでvue.jsの起動中にデータの取得を開始し取得が完了するとブラウザにそのデータ内容を表示させることができます。

elがなにか確認してみよう

ライフサイクルを記述した上の図の中に”el”という文字列を見つけることができます。elはvue.jsインスタンスがマウントを行う要素で、elを指定した要素の中でだけvue.jsを動かすことができます。new Vueで下記のようにしてelプロパティに#appといった要素を特定するidの値を記述します。

要素のidはappである必要はなく任意の名前をつけることができます。またidはdivなどの要素にしているdiv id=”app”です。

var app = new Vue({
  el: '#app',
  data: {

  },
})

このelが一体どのような情報を持っているのか確認してみましょう。elにはthis.$elでアクセスすることができます。thisはvueのインスタンスを表します。

button要素を作ってv-onディレクティブでclickイベントを設定し、クリックが行われたらshowElメソッドを実行しコンソールにthis.$elの中身を表示させます。


<body>
  <div id="app">
    <h1>Hello World</h1>
    <button v-on:click="showEl">show el</button>
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
  el: '#app',
  data: {
  },
  methods:{
    showEl : function(){
      console.log(this.$el)
    }
  }
})
</script> 
</body>

デベロッパーツールのコンソールに<div id=”#app”></div>が表示されます。中身は、document.getElementById(‘app’)を使って取得できるものと同じです。

this.$elの中身を表示
this.$elの中身を表示

getElementById(‘app’)で取得できる要素と同じなので、showElメソッドのconsole.logの前に下記のコードを追加するとinnnerHTMLで中身を書き換えることも可能です。buttonをクリックするとHello WorldがHello Vueに書き換えられることが確認できます。


this.$el.innerHTML = "<h1>Hello Vue</h1>";

ここまでの動作確認でelはnew Vueインスタンスで指定した要素そのものであることがわかりました。

createdとmountedの違い

elの中身がわかったので、ライフサイクルフックのcreatedとmountedの違いを確認しておきましょう。createdとmountedの違いは下記のように説明されているのをよく見かけます。

createdはDOMがまだ作られていない状態で、mountedではDOMが作成された直後の状態です。

DOMの作成、未作成でライフサイクルフックの違いが別れているということなので、this.$elを使ってその違いを確認してみましょう。確認方法はシンプルでcreatedとmountedにconsole.logでthis.$elがそれぞれの状態でどのようになっているか確認するだけです。

this.$elはDOMの要素なのでDOMが作成されていないとthis.$elは存在しません。


new Vue({
  el: '#app',
  data: {
  },
  created : function(){
    console.log('created')
    console.log(this.$el)
  },
  mounted : function(){
    console.log('mounted')
    console.log(this.$el)
  }
})

createdではDOMが作成されていないので、this.$elはundefinedとなっており、mountedではDOMの作成が完成しているので<div id=”app”></div>が表示されます。

createdとmountedでのthis.$elの状態
createdとmountedでのthis.$elの状態

これでcreated, mountedの違いがわかりました。そのため、createdの時にgetElementById(‘id’)を使ってDOMの要素を取得しようとしても取得することはできません。しかしmounted時にはDOMの作成が完了しているのでDOMの要素が取得できるためgetElementByIdだけではなくvue.js以外のライブラリjQuery等(DOMを利用するもの)もこの時点で使用可能となります。

createdでは何が完了しているのか

ではcreatedでは何が完了しているのでしょう。先程まではthis.$elでelの状態を確認しましたが、その中身は見えませんでした。今度はthisを使ってVueインスタンスを確認します。今回はdataにmessageプロパティの設定も行っておきます。


  el: '#app',
  data: {
    message : 'Hello World'
  },
  created : function(){
    this.message = 'Hello Vue'
    console.log('created')
    console.log(this)
  }

Vueインスタンスの作成が完了しているので、設定しているmessageをVueの中で確認することができます。this.messageをcreatedの中で上書きした値も反映されていることが確認できます。これでcreatedでインスタンスの作成が完了、dataオブジェクトがリアクティブになっているという説明を受けても理解することができます。

ここでのリアクティブとは値の更新を行うと更新が反映されるという認識で読み進めてください。
createdの状態でVueインスタンスを確認
createdの状態でVueインスタンスを確認

dataオブジェクトがリアクティブになっているのでcreatedの中でAPIを使ってデータ取得を開始しても取得したデータを設定することができるのでcreatedの中で外部からデータを取得しても問題がないことがわかるかと思います。このことが理解できた上で下記のようなコードを見かけるのも納得できるかと思います。createdの中でデータプロパティusersに外部サーバから取得したデータを挿入しています。


  created :function(){
    axios.get('https://jsonplaceholder.typicode.com/usedrs')
          .then(response => this.users = response.data)
  }

createdとbeforeCreateの違い

beforeCreateでは、dataの中身を確認することができますが、createdのようにmessageの上書きを行うことはできません。


  beforeCreate : function(){
    
    this.message = 'Hello Vue'

    console.log('beforeCreate')
    console.log(this)
}
beforeCreateでdata変更

これでbeforeCreateでインスタンスの作成が完了、dataオブジェクトがリアクティブになっていないという説明を受けても理解することができます。

ここまでの説明を読み終えるとelの理解、beforeCreate, created, mountedのライフサイクルフックの違いも理解できたかと思います。