Vue インスタンスにつて勉強する

# Vue インスタンス
Vueアプリケーションは<font color="orange">Vue関数</font>で**Vueインスタンス**を生成する事で使うことができます。
Vue インスタンスを生成するには、**オプションオブジェクト**を渡します。
全てのオプションの一覧はVue.js公式リファレンスの[**APIリファレンス**](https://jp.vuejs.org/v2/api/#%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3-%E3%83%87%E3%83%BC%E3%82%BF)を参照してください。

```javascript:Vueインスタンス生成
var vm = new Vue({
  // オプションオブジェクト
})
```

Vueは[MVVM(Model-View-ViewModel)](https://qiita.com/homyu/items/046c9a43b15b9e376198)設計に影響をうけて作られています。

## Vue インスタンス生成

Vue インスタンスが作成されると、自身のdataオブジェクトの全てのプロパティをリアクティブシステムに追加します。

```html:html部分
<div id="app">
  <p> {{ userName }} </p>
</div>
```

```javascript:javascript部分
let userData = { userName: '山田太郎' }

let vm = new Vue ({
  el: '#app',
  data: userData
})
```

データを変更すると、Viewが再レンダリングされます。
ブラウザ上の開発者ツールのConsoleで試してみます。

```javascript:ブラウザ上の開発者ツールのConsole
// インスタンスのプロパティに値を代入する
vm.userName = '川田良助' // 山田太郎　=> 川田良助

// インスタンスのプロパティに代入された元のデータにも反映される
vm.userName // => 川田良助
userData.userName // => 川田良助

// 元のデータに値を代入する
userData.userName = '加藤一二三' // 川田良助　=> 加藤一二三

// 元のデータが書き換わるとインスタンスのプロパティも書き換わります
userData.userName // => 加藤一二三
vm.userName // => 加藤一二三
```

新しくプロパティを追加する場合はビューの再レンダリングは行われません。

```html:html部分
<div id="app">
  <p> {{ userName }} </p>

  <!-- Property or method "userAge" is not defined on the instanceというwarnが発生しますがプロパティがインスタンスに定義されていないとどうなるか確認するためのコードなので無視します -->
  <p> {{ userAge }} </p>
</div>
```

```javascript:javascript部分
let userData = { userName: '山田太郎' }

let vm = new Vue ({
  el: '#app',
  data: userData
})
```

ブラウザ上の開発者ツールのConsoleでインスタンスにuserAgeプロパティを追加し値を代入します。

```console:ブラウザ上の開発者ツールのConsole
vm.userAge = 23
23
```

```:ブラウザの画面
山田太郎
※インスタンスにプロパティを追加したタイミングで再レンダリングされ23と表示さてほしかった
```

新しく追加は行えますが画面には再レンダリングされません。  
ですが、続けて定期されていたプロパティの値を変更してみます。

```console:ブラウザ上の開発者ツールのConsole
vm.userName = '加藤一二三'
"加藤一二三"
```

```:ブラウザの画面
加藤一二三
24
```

再レンダリングが行われ、追加で定義を行ったuserAgeもレンダリングされてますが、初期レンダリングの時点でConsoleに警告文が表示されているのでこのように追加し無理やりレンダリングさせる方法は意図せぬバグを生むのでやめましょう。  

後でプロパティが必要になることがわかっているならば、空で存在しない場合でも初期値を設定しておきましょう。

```html:html部分
<div id="app">
  <p> {{ userName }} </p>

  <p> {{ userAge }} </p>
</div>
```

```javascript:javascript部分
let userData = { 
  userName: '山田太郎',
  userAge: null
}

let vm = new Vue ({
  el: '#app',
  data: userData
})
```

Vueインスタンスは幾つかの便利なプロパティとメソッドを持っています。  
これらはユーザ定義のプロパティと区別するために頭に<font color="orange">＄</font>が付けられています。

```html:html部分
<div id="app">
  <p> {{ userName }} </p>
</div>
```

```javascript:javascript部分
let userData = { 
  userName: '山田太郎',
}

let vm = new Vue ({
  el: '#app',
  data: userData
})
```

ブラウザ上の開発者ツールのConsoleで試してみます。

```console:ブラウザ上の開発者ツールのConsole
vm.$data === data
true

vm.$el === document.getElementById('app')
true

```

インスタンスのプロパティとメソッド一覧は[**APIリファレンス**](https://jp.vuejs.org/v2/api/#%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3-%E3%83%87%E3%83%BC%E3%82%BF)を参照してください。

## インスタンスライフサイクルフック
Vueインスタンスは、生成時に一連の初期化を行います。
その初期化の過程、特定の段階でユーザ自身のコードを追加する、幾つかの<font color="orange">**ライフサイクルフック(lifecycle hooks)**</font> と呼ばれる関数を実行します。
全てのライフサイクルフックは、**this**が Vue インスタンスを指す形で実行されます。

### ライフサイクルフック一覧

+ beforeCreate  
インスタンスが初期化されるときに同期的に呼ばれる
+ created  
インスタンスが作成された後に同期的に呼ばれる  
サーバサイドとクライアントサイドの両方で呼ばれる
+ beforeMount  
インスタンスがマウントされる前に呼ばれる  
beforeMountからはクライアントサイドのみで呼ばれる
+ mounted  
インスタンスがマウントされた後に呼ばれる
+ beforeUpdate  
状態を更新し、Virtual DOMが再描画される前に呼ばれる
+ updated  
状態を更新し、Virtual DOMが再描画された後に呼ばれる
+ beforeDestroy  
インスタンスが破棄される前に呼ばれる
+ destroyed  
インスタンスが破棄された後に呼ばれる

どのタイミングで呼ばれるかを書きましたが、もう少し詳しく書かれている方がいるのでリンクを載せておきます。

[Vue.jsのライフサイクルメモ](https://qiita.com/kurosame/items/6ab7622fe30c299a693e)

### <font color="red">注意</font>
インスタンスプロパティまたはコールバックでアロー関数 を使用しないでください。
アロー関数は**this**をもたないため、**this**は他の変数と同様に見つかるまで親スコープを[レキシカル](https://qiita.com/Urushibara01/items/455f8fc41f2a01fff78c)に探索され、エラーが発生します。

```javascript:例
created: () => console.log(this.a)
vm.$watch('a', newValue => this.myMethod())
```

```console:エラー内容
Uncaught TypeError: Cannot read property of undefined

Uncaught TypeError: this.myMethod is not a function
```

## ライフサイクルダイアグラム
今はこのダイアグラムを完全に理解する必要はありませんが、先ほど解説したライフサイクルフックに注目してみてください。

![公式リファレンス参照](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398252/92d874ac-c3bc-131a-1d66-5cbf6fbce66b.png)

## 参考資料
[Vue.js公式リファレンス](https://jp.vuejs.org/index.html)
[Vue.jsのライフサイクルメモ](https://qiita.com/kurosame/items/6ab7622fe30c299a693e)
[レキシカルとスタティックの違い](https://qiita.com/Urushibara01/items/455f8fc41f2a01fff78c)