5分で分かるVue.jsの基礎


# 参考

[Vue Mastery](https://www.vuemastery.com/courses/intro-to-vue-js/vue-instance/)
[The Net Ninja Vue JS 2 Tutorial](https://www.youtube.com/watch?v=3ROjxrSa5pk&list=PL4cUxeGkcC9gQcYgjhBoeQH7wiAyZNrYa&index=3&t=0s)

# Vue.js とは

**Vue.js**とはユーザーインターフェースを構築するための**`フレームワーク`**（**アプリケーションの基本的な機能やルールを提供する骨組み**）で、**`主にSPA（シングルページアプリケーション）`**を構築する時に向いています。「**学習コストの低さ**」「**スケールの柔軟性**」「**公式ドキュメントの充実**」が魅力 :chicken::fire:

#### **`SPA（シングルページアプリケーション）`**とは

JavaScriptでDOMを操作しページを切り替える単一ページで構成されるWebアプリケーション

#### **`DOM / 仮装DOM`** とは

`DOM` : Document Object Modelの略で、**JavaScriptからHTMLやCSSのデータを取得、操作するための仕組み**。htmlドキュメントをツリー構造として表現したもの。

```index.html
<html>
  <head>
    <title>Vue.js</title>
  </head>
  <body>
    <h1>DOMとは</h1>
  </body>
</html>
```
上記のマークアップは下記のような「**DOMツリー**」として表現されます。

```index.html

html
├── head
│   └──title
│       └──Vue.js-lesson2
└── body
    └── h1
        ├──DOMとは
        └──h1タグのコメント

```

`仮装DOM` : 仮想DOMはバインディングしたデータを元に作られ、仮想DOMを元にDOMを作成する。
仮想DOMを利用する目的の1つとして、描画処理の性能を向上させる狙いがあり、実際のDOMでの描画処理では、仮想DOMの**差分検出アルゴリズム**で**描画処理前の仮想Nodeツリーから**更新対象を抽出する。
描画対象となるDOMに対して、Nodeの新規追加・更新・削除といったDOM操作を行う。


# Vueアプリケーションの作成

アプリケーション作成のために、コンストラクタ関数`vue`を使ってルートとなる`vueインスタンス`を作成する。`vue インスタンス`はアプリケーションの**心臓部分**。

```main.js

var app = new Vue ({
  // オプション
})

```

※ 慣例的に**app**や**vm**などの変数名が使用される。


## オプションの構成

```main.js

var app = new Vue ({
  el: '#app',
  data: {
    message: 'Vue.js'
  },
  computed: {
  },
  method: {
  },
  created:  function(){
  }
})

```
```index.html
<div id='app'></div> //ここが対象要素となる
```

* `elオプション` : マウントする**DOM要素**（アプリケーションを紐付ける要素のセレクタ）
* `data`: アプリケーションで使用するデータです。オブジェクトや配列も登録できる。ここで定義されるプロパティは**`リアクティブなプロパティ`**へと変換される。

```main.js

var app = new Vue ({
  el: '#app',
  data: {
    message: 'Vue.js' //変化を検知できるようになる
  }
})
```

####`リアクティブなプロパティ / データ`とは？

DOMの同期を自動で行う「**データバインディング**」を行うには、
テンプレートで使用するデータは「**リアクティブなデータ**」として定義する必要がある。
`リアクティブなデータ`とはVue.jsによって取得した時(get)、または代入した時(set)のフック処理が登録された"_**反応のできるデータ**_"のこと。

####`データバインディング`
**データと描画を同期させる仕組み**のことを「**データバイディング**」と呼ぶ。
HTMLで作られたUIを操作するのに、viewの管理（DOMの更新など） は必要不可欠。

ライブラリを一切利用せずにJavaScriptでDOMを更新した時は、

```app.js

var el = document.getElementById('text') //要素を探す
el.innerText = '新しいテキスト'              //要素を更新する

```

上記の処理で、UIのパターンごとにDOMを更新するのは、
UIのパターンが増えれば、増えるほど大変になっていってしまう・・
のでこういう自動的に描画が同期できるシステムはとても便利。


## `computed` : **算出プロパティ**

算出プロパティは処理に名前をつけて、テンプレート上で変数の様に使うことができる関数。

【 特徴 】

* 一度計算を行った場合、再度関数を呼び出しても依存しているデータに変更がない限りキャッシュを返す（変更箇所だけが返される）
* プロパティ呼び出しの時は `()`が**不**必要
* リアクティブなプロパティが変更された時に呼ばれるのが`computedプロパティ`

## `methods` : **メソッド**

オブジェクトの操作を処理を定義したもの

【 特徴 】

・ 計算結果をキャッシュしない
・ そのため再描画されるたびにもう一度、計算が実行される
・ イベントに反応する


## `created` Vue.jsのライフサイクル

**ライフサイクル**とは、`Vueインスタンス`のはじまり（初期化）からおわり（破棄）されるまでの一定のサイクルのこと。あらかじめ登録された処理を、Vueインスタンスの特定のタイミングで差し込みます。
こうした処理を割り込ませる仕組みを「**フック**」と呼ぶ。

コンポーネントのライフサイクルフックがどの時点で実行されるかは以下になります。
[ライフサイクルダイアグラム](https://jp.vuejs.org/v2/guide/instance.html#%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%80%E3%82%A4%E3%82%A2%E3%82%B0%E3%83%A9%E3%83%A0)

| メソッド | 説明 |
|:--|:--|
| **beforeCreated** | インスタンスが作成され、初期化される前に実行 |
| **created** | インスタンスが作成され、初期化された後に実行 |
| **beforeMount** | DOMがマウントされる直前に実行 |
| **mounted** | DOMがマウントされる直後に実行 |
| **beforeUpdate** | リアクティブプロパティが変更されて、変更されたデータがDOMに反映される前に実行 |
| **updated** | リアクティブプロパティが変更されて、変更されたデータがDOMに反映された後に実行 |
| **beforeDestroy** | Vueインスタントが破棄される前に実行|
| **destroyed** | Vueインスタンスが破棄された後に呼び出される |

**`created`** : リアクティブなプロパティの初期化が完了しているので、dataやmethodsを参照することができる。**APIにリクエストを送信してデータを送信し、リアクティブプロパティに追加していく処理はcreated内に記述していくと良い。**


# Vue.jsの基本機能

### テキストと属性のデータバインディング
#### Mustache構文 `{{}}`

```main.js

var app = new Vue ({
  el: '#app',
  data: {
    message: 'Vue.js',
    list: ['ねこ', 'いぬ', 'とり']
  },
  computed: {
  },
  method: {
  },
  created:  function(){
  }
})

```

`dataオプション`に定義した`message`プロパティの値を画面に表示したいときは、
`{{}}`**マスターシュ構文（Mustache：口髭）** で囲みテンプレートに記述します。

```index.html
<h1>{{message}}</h1> // Vue.js と表示される

<h1>{{list[0]}}</h1>  // ねこ と表示される 

```

### ディレクティブ

「Vue.js」では、**ディレクティブ**と呼ばれる**`v-接頭辞`**で始まる属性をHTML内で使用できます。
**ディレクティブ**は主に**データバインディング**を行うために使用される。

#### **`v-bind ディレクティブ`**

簡単なテキストのデータバインディングであればMustache構文を使えましたが、**html要素の属性をデータバインディングする場合**にはMustache構文はエラーとなり使えません。

```index.html

<div id="error">
  <a href="{{ url }}">Google</a> // 属性では展開されない！
</div>

```

```app.js
var app = new Vue({
  el: "#example-error",
  data: {
    url: "https://google.com"
  }
});
```

そこで使用するのが **`v-bindディレクティブ`** です。
**v-bindディレクティブ を使えばDOM要素の属性を動的に切り替えることができます。**


```index.html
<タグ v-bind:属性=“プロパティ”>～</タグ>
```

```index.html
<div id="example">
  <a v-bind:href="url">Google</a>
</div>
```

```app.js
var app = new Vue({
  el: "#example",
  data: {
    url: "https://google.com"
  }
});
```

####**`v-bind ディレクティブ`**の省略

**v-bind** は省略して、**`:`**のみで省略できます。

```index.html
<div id="example">
  <a :href="url">Google</a>
</div>
```


#### **`v-on ディレクティブ`**

`v-onメソッド`は**イベント処理をする**ためのディレクティブです。

（例） clickイベントを設定する

```index.html

<div id="app">
  <p>{{ count }}回クリック</p>
  <button v-on:click="increment">このボタンでカウントを増やす</button> //increment メソッドが呼び出される
</div>

```

```main.js

var app = new Vue ({
  el: '#app',
  data: {
    count: 0
  },
  method: {
    increment: function(){
      this.count += 1 // thisはdata内のリアクティブデータを指す
    }
  },
})

```

#### `v-on`ディレクティブの省略記法について

**v-on** は省略して、**`@`**で省略できます。

```index.html

<div id="app">
  <p>{{ count }}回クリック</p>
  <button @click="increment">このボタンでカウントを増やす</button> //increment メソッドが呼び出される
</div>

```


#### **`v-show ディレクティブ`**

v-showディレクティブは、**式が真のときのみ要素を表示するディレクティブ**です。

```index.html
<div id="app">
　<div v-show="ok">
    <p>Hello</p>
  </div>
</div>
```

```main.js
var app = new Vue({
  el: '#app',
  data: {
    ok: true // 切り替える
  }
})
```

##### `v-if`と`v-show`の違いと使い分け

`v-if` :条件を満たさなかった場合、要素はDOmレベルで削除される。

![スクリーンショット 2019-12-21 14.29.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446210/23e63421-b47d-4274-23d9-076279c52ae3.png)


`v-show` :条件を満たさなかった場合、`display;none`が付与され、非表示になる。

![スクリーンショット 2019-12-21 14.31.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446210/907c9817-0f7a-247e-81da-0158e42e2bb3.png)


### 条件分岐

vue.jsはテンプレートベースで条件分岐を記述します。
`v-ifディレクティブ`は、`v-showディレクティブ`同様に式の真偽を判定して要素を表示させるディレクティブ

```index.html

<p v-if="id === 1"> 条件がtrueの時の表示 </p>
<p v-else-if="id === 2"> 上記がfalseで、else-ifでの条件がTrueの表示 </p> //今回はこのpタグが表示される
<p v-else> 上記のどちらの条件もfalseの時の表示 </p>

```

```main.js

var app = new Vue ({
  el: '#app',
  data: {
    message: 'Vue.js',
    id: 2, // ← ここ
  },
})

```