Vue.jsディレクティブの使い方まとめ

最近やっているプロジェクトでjQueryを使ってたのですが、jQueryの面倒さに発狂したくなってしまい、なんとかならないものかと思っていたところ、Vue.jsに出会いましたので学習をはじめました。

# 参考
 - [Vue.js 公式Document](https://jp.vuejs.org/)
 - [udemy: Vue JS入門決定版！jQueryを使わないWeb開発 - 導入からアプリケーション開発まで体系的に動画で学ぶ](https://www.udemy.com/learn-vuejs/)

今回udemyを一通り受講し、振り返りをしているため非常に参考とさせていただきました。非常に分かりやすい構成になっているため、初めて学習を始める人はまず受講してみることをオススメ致します。


# Vue.jsの基本構文
## データバインディング
### Mustache構文
Vue.jsではMustache構文を使うことで、簡単にVueインスタンスデータとHTMLを結びつけることができます。
このデータの結びつけのことを`データバインディング`といいます。

下記の例を表示すると `{{ message }}` にはHello Vue.js!が表示されます。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Vue Sample</title>
  </head>
  <body>
    <div id="example">
        {{ message }}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  </body>
</html>
```

```javascript:main.js
var app = new 
Vue({
  el: "#example",
  data: {
    message: "Hello Vue.js!"
  }
});
```

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

※以降Vueに関わる部分のみHMTLを記載

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

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

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

__例1：href属性のデータバインディング__
下記例だとhref属性のurlにGoogleのURLがデータバインディングされます。

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

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

__例２:value属性のデータバインディング__
下記例ではinputタグのvalue属性がデフォルトで`おはよう！`と表示されます。

```html:index.html
<div id="example2">
  <input v-bind:value="message">
  <p>{{ message }}</p>
</div>
```

```javascript:main.js
var app = new Vue({
  el: "#example2",
  data: {
    message: "おはよう！"
  }
});
```

しかし初期値の`おはよう！`は正しく表示されていましたが、文字を書き換えた時にpタグが書き換わっていなかったことに気づくと思います。

これはv-bindによるデータバインディングは

```
　・jsで更新したdataはテンプレートに更新されるが、
　・テンプレート側で更新してもdataが更新されない
```
という性質があるためです。そこで登場するのが、`v-on` メソッドです。

### v-on
`v-on`メソッドはイベント処理をするためのディレクティブです。
input要素のテキストエリアに入力する度にinputイベントが発生するので、v-bindに追加でv-onを追加してdataを更新する処理を追加します。

```html:index.html
<div id="example">
  <input 
    v-bind:value="message"
    v-on:input="message = $event.target.value"
  >
  <p>{{ message }}</p>
</div>
```

```javascript:main.js
var app = new Vue({
  el: "#example",
  data: {
    message: "おはよう！"
  }
});
```

 1. 初期値で`message`におはよう！が入力されています
 2. そのためMustasche構文でかいているpタグにも`おはよう！`が表示されます
 3. 入力欄に`おはよう！`の！を削除するとinputイベントが発生し、messageを書き換えます
 4. するとMustasche構文でかいているpタグにも`おはよう`に更新されます

このようにjsからテンプレートのデータを更新するだけでなくく、テンプレートからもデータを更新することを __双方向データバインディング__といいます。下記の2行は全く同じ表現で、どちらもmessageに対して双方向データバインディングすることができます。

### v-model
v-bindとv-onを組み合わせた双方向データバインディングの例を示しましたが、これは`v-model`というディレクティブで表現することができます。

```javascript
  // どちらも同じ
  <input v-model="message">
  <input v-bind:value="message" v-on:input="message = $event.target.value">
```

### v-bindとv-onの省略記法
v-bindとv-onは頻繁に使用するため省略記法があります。

|ディレクティブ|完全な構文|省略記法|
|:--|:--|:--|
|:v-bind|`<a v-bind:href="url"> ... </a>`|`<a :href="url"> ... </a>`|
|:v-on|`<a v-on:click="func"> ... </a>`|`<a @click="func"> ... </a>`|


## 繰り返し処理
### v-for
`v-for`を使えば繰り返し文を使うことができます。
また`v-for="(user, index) in users"`とすることで配列のキーを取り出すことも可能です。

```html:リストの例
<ul id="example">
  <li
   v-for="(user, index) in users"
  >
    {{ member }}
  </li>
</ul>
```
```javascript
var app = new Vue({
  el: "#example",
  data: {
    users: ["佐藤", "鈴木", "山田"]
  }
});
```

## 表示・非表示の切り替え
### v-if, v-if-else, v-else
`v-if`ディレクティブではブロックを条件に応じて描画することができます。

```html
<div id="app">
　<div v-if="toggle">
    <p>Hello</p>
  <div v-else>
    <p>World</p>
  </div>
</div>
```

```javascript
var app = new Vue({
  el: '#app',
  data: {
  	toggle: true // 切り替える
  }
})
```

### v-show
`v-show`ディレクティブは属性値がtrueとなる場合に要素を表示します。

```html
<div id="app">
　<div v-show="toggle">
    <p>Hello</p>
  </div>
</div>
```

```javascript
var app = new Vue({
  el: '#app',
  data: {
  	toggle: true // 切り替える
  }
})
```

### v-ifとv-showの比較と使い分け
#### 比較
v-ifとv-showは表示・非表示の方法に明らかな違いがあります。

||v-if|v-show|
|:--|:--|:--|
|切り替え方法|ブロックごと作成・削除|ブロックを残したまま表示・非表示を切り替え|
|初期描画コスト|低い|高い|
|描画切り替えコスト|高い|低い|

v-ifは非表示にする時にブロックごと削除します。
![スクリーンショット 2019-08-11 12.45.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234184/378f9695-af65-7fa8-f141-b6f1d67b21e6.png)

一方でv-showは非表示にする時にブロックに対してCSSの`display:none`を使って切り替えます。
![スクリーンショット 2019-08-11 12.44.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234184/6cb3ed17-ef5c-ec72-07c9-a415787a7999.png)

#### 使い分け
__v-if__
　・ 初期描画コストが低く、描画切り替えのコストが高い
　・ そのため切り替えの頻度が低いなら、初期描画コストの低い`v-if`を使用する
__v-show__
　・ 初期描画コストが高く、描画切り替えのコストが低い
　・ そのため切り替えの頻度が多いなら、描画切り替えコストの低い`v-if`を使用する

## 算出プロパティ
内容にボリュームがあるためお引越ししました。
[[Vue.js]算出プロパティとメソッドの違い](https://qiita.com/okerra/items/cda378436ed060e83a8c)

# さいごに
今回初めてVue.jsを使ってみましたが、jQueryのように直接DOM操作をするわけでなく、少ない量でかつわかりやすくDOMの操作をすることができ非常に期待が高まりました。
使い分けに関する情報など、初学者に少しでも役に立てば幸いです。