Vue.js を１から学んでみた〜ディレクティブ〜

[Vue.js を１から学んでみた。](https://qiita.com/sh-watanabe/items/c7fc086a4ea5c707fbd3)にて書いてきましたが、
長くなり編集しにくくなってきたので、分割しました（こんなやりかたしないのかな？知りたい。）

## 4.ディレクティブ

特徴としては、以下かと。

* `v-` から始まる特別な属性
* 属性値は、**単一の JavaScript 式**を期待する（例外は`v-for`）
* 属性値の式が変更された時に、DOMを更新する
* 省略記法あり。
  * 例：`<a v-bind:href="url"> ... </a>` → `<a :href="url"> ... </a>`

`v- `のディレクティブについて捉えることが必要そうなので、まとめようと思います。

※次の記事にもまとまっており、参考にもさせていただきました。
[体で覚えるVue.js - ディレクティブ編 〜 JSおくのほそ道 #023](https://qiita.com/hosomichi/items/25041c1d46452de84aa6)

### v-text
* DOMの内側に展開。
* Mustache構文（{{}}で囲んだコード）と一緒。
* 省略系→{{}}

*サンプルコード*

```sample1.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-1">
  <!-- フィールド展開の例 -->
  <p v-text="message"></p>
  <p>{{ msg }}</p>
  
  <!-- メソッド展開の例 -->
  <p v-text="showMessage()"></p>
  <p>{{ showMsg() }}</p>
</div>
```

```sample1.js
var vm = new Vue({
  el: '#app-1',
  data: {
    message: 'Hello Vue.js!',
    msg: 'サンキュー'
  },
  methods: {
    showMessage: function () {
      return "はろー、Vue.js"
    },
    showMsg: function () {
      return "Thank you!!"
    }
  }
})
```

*結果*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/972509a0-3d04-c336-10b3-21f74afbbe92.png)

### v-once
* 1度DOM展開したら、そのあとは変更させない。
* なんかの処理で、バインディングしたデータが変更されても、描画を変更させたくないときに有効。
  * 個人的にはこれを使うのは最終手段かなと。感覚的に。
* 省略系→なし

*サンプル（v-onceを使わない）*

```sample2-1.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-2">
  <p v-text="message"></p>
  <p v-text="showMessage()"></p>
</div>
```

```sample2.js
var vm = new Vue({
  el: '#app-2',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    showMessage: function () {
      this.message = 'hoge';
      return "はろー、Vue.js"
    }
  }
})
```
*結果（「Hello Vue.js!」がshowMessage()で書き換えられて表示される）*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/30b01414-cfe9-70d4-d918-3115d1c40acb.png)

*サンプル（v-onceを使う・JavaScriptは変更しないので割愛）*

```sample2-2.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-2">
  <!-- v-onceを追加 -->
  <p v-once v-text="message"></p>
  <p v-text="showMessage()"></p>
</div>
```

*結果（「Hello Vue.js!」が表示される）*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/eb5f5452-a087-e60a-456f-ae4e9ef3425f.png)

### v-html
* DOMの内側に展開。
  * v-textは「文字列」で展開する
  * v-htmlは「HTML」で展開する
* HTMLをそのまま展開されるので、XSSに注意して使うことが必要。
* 省略系→なし

*サンプルコード：h1タグを表示させたいときー*

```sample3.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-3">
  <p v-text="message"></p>
  <p v-html="message"></p>
</div>
```

```sample3.js
var vm = new Vue({
  el: '#app-3',
  data: {
    message: '<h1>タイトルです<h1>'
  }
})
```

*結果*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/9d488a9a-fa25-d205-0928-bb843b1eeac5.png)

### v-bind（その１：属性値）
* htmlタグの属性に埋め込む時に使用。
* 引数が必要なディレクティブ。引数は:の後ろに設定する`v-bind:href="url`
* 使う頻度がスーパー高そう。
* 省略系→`:href='url'`のように、コロンだけでOK。

*サンプルコード：aタグのリンク先を設定したいときー*

```sample4.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-4">
  <!-- :(コロン)の後に引数を設定する-->
  <a v-bind:href="url">モノタス</a>


  <!-- 省略系
  <a :href="url">モノタス</a>
  -->
</div>
```

```sample4.js
var vm = new Vue({
  el: '#app-4',
  data: {
    url: 'https://www.monotas.net/'
  }
})
```

*結果*
![aaa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/daeac771-ac8b-b89c-3ffb-5a0082d10cc5.gif)

### v-bind（その２：属性）
* htmlタグそのものを定義することも可能
* 属性を[]で囲うことで指定可能。例：`<a :[attr]="hogehoge">`
* つまり、v-bindだけで、各種タグに属性とそのvalueのバインディングができる。
* これも使う頻度がスーパー高そう。

```sample5.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-5">
  <a :href="monotas_url">モノタス</a>
  <br>
  <a :[attr]="jta_url">日本テニス協会</a>
</div>
```

```sample5.js
var vm = new Vue({
  el: '#app-5',
  data: {
    attr: 'href',
    monotas_url: 'https://www.monotas.net/',
    jta_url: 'https://www.jta-tennis.or.jp/'
  }
})
```

*結果*
![aaa2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/a3de4bb7-dcfb-483f-0139-8a6ced83f42e.gif)

### v-bind（その３：オブジェクト化）
* 1つのタグに複数のv-bindを指定することもできるが、一つのオブジェクトとして記載することも可能。
* Vueフィールドにオブジェクトを用意して、それを`v-bind`で指定することも可能。
* 見た目すっきり系でもあるし、DOMの操作しやすくなりそうな感覚。まだふんわりとしかわかってない。

```sample6.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-6">
  <!-- 複数指定できる -->
  <a :id="monotas_id" :href="monotas_url">モノタス（省略系でそれぞれ指定）</a>
  <br>
  <!-- 一つのオブジェクトでも書ける -->
  <a v-bind="{id: monotas_id, href: monotas_url}">モノタス（オブジェクトを直接指定）</a>
  <br>
  <!-- VueインスタンスフィールドのオブジェクトもOK -->
  <a v-bind="monotas">モノタス（Vueインスタンスのオブジェクトを指定）</a>
  <br>
</div>
```
```sample6.js
var vm = new Vue({
  el: '#app-6',
  data: {
    attr: 'href',
    monotas_id: 2,
    monotas_url: 'https://www.monotas.net/',
    monotas: {
    	id: 2,
      href: 'https://www.monotas.net/'
    }
  }
})
```
*結果：全て同じIDとurlが設定されている*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/48bea880-2f7e-f578-8eee-d5d0095a52e3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/553447bc-94a3-ead2-ed04-5174009deb92.png)


### v-on（その１：基本）
* クリック等のDOMが提供しているイベントのリスナー。
* イベント発火時のJavaScriptの実行が可能。
* 引数が必要なディレクティブ。引数は:　の後ろに設定する`v-on:click="change"`
  * `click`はDOMが提供しているイベント
  * `change`が Vueで定義したメソッド。
* 使う頻度は超スーパー高そう。
* 省略系→`@click="change"`のように、コロンだけでOK。

*サンプルコード：clickイベントの例。ボタンが押されたら文字列を変更します的なときー*

```sample7.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-7">
  <button v-on:click="change">クリックすると文字が変わります</button>
  <p>{{ first_str }}</p>
</div>
```
```sample7.js
var vm = new Vue({
  el: '#app-7',
  data: {
    first_str: '最初に表示されています',
    clicked_str: 'ボタンが押されました'
  },
    methods:{
      change: function() {
      	this.first_str = this.clicked_str
      }
    }
})
```
*結果*
![aaa3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/920c6d89-33a6-0e61-7d33-7e34943435e3.gif)

### v-on（その２：引数とイベント）
* v-onでメソッドを実行する際に、引数を渡すことが可能。`change('モノタス')`
* DOMイベントをそのまんま渡すことも可能。`$event`という特別な変数を指定する。`change($event, 'モノタス')`

*サンプルコード：引数とイベントオブジェクトを渡した時の例*

```sample8.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-8">
  <!-- $eventでイベントオブジェクト渡します -->
  <button v-on:click="change($event, '株式会社モノタス')">クリックすると文字が変わります</button>
  <p>{{ first_str }}</p>
  <p>{{ event_name }}</p>
</div>
```
```sample8.js
var vm = new Vue({
  el: '#app-8',
  data: {
    first_str: '最初に表示されています',
    clicked_str: 'ボタンが押されました',
    event_name: 'イベントが表示されます'
  },
    methods:{
      change: function(event, msg) {
        this.first_str = msg
        this.event_name = event.target.tagName
      }
    }
})
```
*結果*
![aaa4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/ba04e87a-8323-406d-e5ea-2999ca19db9d.gif)

### v-on（その3：イベントをJavaScriptから指定）
* click等のDOMイベントは、JavaScriptからも指定できる

*サンプルコード：その2のコードをちょっと変更

```sample8-2.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-8-2">
  <!-- vm_eventに変更 -->
  <button v-on:[vm_event]="change($event, '株式会社モノタス')">クリックすると文字が変わります</button>
  <p>{{ first_str }}</p>
  <p>{{ event_name }}</p>
</div>
```
```sample8-2.js
var vm = new Vue({
  el: '#app-8-2',
  data: {
    first_str: '最初に表示されています',
    clicked_str: 'ボタンが押されました',
    event_name: 'イベントが表示されます',
    vm_event: 'click' // このイベントを設定
  },
    methods:{
      change: function(event, msg) {
        this.first_str = msg
        this.event_name = event.target.tagName
      }
    }
})
```

### v-on（その4：引数となるDOMイベント）

DOMイベントの一覧は以下を参照。
https://developer.mozilla.org/ja/docs/Web/Events

上記のページの内、以下をよく使うと想定。
* キーボードイベント
* マウスイベント
* ドラッグ & ドロップイベント
* フォームイベント
* フォーカスイベント

### v-model（その１：基本）
* Vueのインスタンスの変更をリアルタイムにDOM要素へ展開してくれる
* 逆も然りであり、DOM要素の更新をVueインスタンスへ展開してくれる
* 双方向バインディング
* 使う頻度は超スーパーすげー高そう。
* 省略系→なし

*サンプル：DOM要素を更新した時に、Vueインスタンスの情報が更新されることの例*

#### テキスト

* inputタグで、`v-model`を使った場合と、使わずに`v-bind`と`v-on`を使った場合で、同じことができる。
* `v-model`の方がシンプル。

```sample9.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9">
  <p>タイトル「v-bind ＋ v-on で対応」</p>
  <input 
    v-bind:value="message_1"
    v-on:input="message_1 = $event.target.value"
  >
  <p>表示：{{ message_1}}</p>
  
  <hr>
  
  <p>タイトル「v-model で対応」</p>
  <input v-model="message_2">
  <p>表示：{{ message_2}}</p>
</div>
```
```sample9.js
var vm = new Vue({
  el: '#app-9',
  data: {
    message_1: 'v-bind ＋ v-on で対応',
    message_2: 'v-model で対応'
  }
})
```
*結果*
![aaa7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/9c8d822f-bd8f-73b9-9b4e-f1e8486e7a52.gif)

#### テキストエリア

* 改行もちゃんと反映される

```sample9-1.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-1">
  <textarea
      id="ta"
      cols="30"
      rows="10"
      v-model="msg1"
  ></textarea>
  
  <pre>{{msg1}}</pre>
</div>
```
```sample9-1.js
var vm = new Vue({
  el: '#app-9-1',
  data: {
    msg1: '初期文字列'
  }
})
```

*結果*
![aaa16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/3a927ec9-1ba7-f3e8-635b-29602974e3c8.gif)

#### チェックボックス

* 単一チェックボックスと、複数チェックボックスで、dataのtypeが変わるので注意。

**単一チェックボックス**

* チェックすることで、true/falseが切り替えられる
* dataのtypeは**boolean**となる

```sample9-1-2.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-1-2">
  <input
    type="checkbox"
    id="hasBoll"
    v-model="hasBoll"
  >
  <lavel for="hasBoll">ボール持ってる</lavel>
  <p>
    {{hasBoll}}
  </p>
</div>
```

```sample9-1-2.js
var vm = new Vue({
  el: '#app-9-1-2',
  data: {
    hasBoll: false // 型がboolan
  }
})
```

*結果*
![aaa17.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/488faa82-8650-f62e-aa6d-2b1d06478554.gif)

**複数チェックボックス**

* チェックボックスの**`v-model`に同じフィールド名を設定する**と、勝手にグルーピングしてくれる。
* チェックすることでvalueが配列に設定される
* dataのtypeが**配列**になる

```sample9-1-3.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-1-3">

  <input
    type="checkbox"
    id="1"
    v-model="birthMonthList"
    value="1月~4月"
  >
  <label for="1">1〜4月</label>
  
  <input
    type="checkbox"
    id="2"
    v-model="birthMonthList"
    value="5月~8月"
  >
  <label for="2">5〜8月</label>
  
  <input
    type="checkbox"
    id="3"
    v-model="birthMonthList"
    value="9月~12月"
  >
  <label for="3">9〜12月</label>
  
  <p>
    {{ birthMonthList }}
  </p>
</div>
```

```sample9-1-3.js
var vm = new Vue({
  el: '#app-9-1-3',
  data: {
    birthMonthList: []
  }
})
```
*結果*
![aaa18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/0f2988d3-522b-4dd6-d7a7-266bf15c9e0e.gif)

#### ラジオボタン

* ラジオボタンの**`v-model`に同じフィールド名を設定する**と、勝手にグルーピングしてくれる。
* チェックすることでvalueが配列に設定される
* dataのtypeが**文字列**になる

```sample9-1-4.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-1-4">

  <input
    type="radio"
    id="1"
    v-model="birthMonth"
    value="1月~4月"
  >
  <label for="1">1〜4月</label>
  
  <input
    type="radio"
    id="2"
    v-model="birthMonth"
    value="5月~8月"
  >
  <label for="2">5〜8月</label>
  
  <input
    type="radio"
    id="3"
    v-model="birthMonth"
    value="9月~12月"
  >
  <label for="3">9〜12月</label>
  
  <p>
    {{ birthMonth }}
  </p>
</div>
```
```sample9-1-4.js
var vm = new Vue({
  el: '#app-9-1-4',
  data: {
    birthMonth: ""
  }
})
```
*結果*
![aaa18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/2e5f3a21-098c-0a2d-b28b-ce0b0d19fc59.gif)


#### セレクトボックス

* 単一選択セレクトボックスと、複数選択セレクトボックスで、dataのtypeが変わるので注意。

**単一選択セレクトボックス**

* dataのtypeは**String**となる

```sample9-1-5.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-1-5">
  <span>出身地</span>
  <select v-model="birthArea">
    <option v-for="item in areas" :key="item">{{item}}</option>
  </select>
  <p>
    {{birthArea}}
  </p>
</div>
```
```app9-1-5.js
var vm = new Vue({
  el: '#app-9-1-5',
  data: {
    birthMonth: "",
    areas: ["荒川区", "台東区", "足立区"],
    birthArea: '荒川区'
  }
})
```
*結果*
![aaa18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/197b4ad0-2664-d55d-580b-f495fde30b66.gif)

**複数選択セレクトボックス**

* dataのtypeは**配列**となる

```sample9-1-6.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-1-6">
  <span>出身地</span>
  <!-- multipleをつける -->
  <select v-model="birthArea" multiple>
    <option v-for="item in areas" :key="item">{{item}}</option>
  </select>
  <p>
    {{birthArea}}
  </p>
</div>
```
```sample9-1-6.js
var vm = new Vue({
  el: '#app-9-1-6',
  data: {
    birthMonth: "",
    areas: ["荒川区", "台東区", "足立区"],
    birthArea: []
  }
})
```
*結果*
![aaa19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/a914d8d2-3285-cf07-1d46-f6e74fa49512.gif)



### v-model（その2：修飾子）

#### .lazy修飾子

* カーソルが離れた瞬間に、DOM要素の更新をVueインスタンスへ展開してくれる。
* メールアドレスの入力とか、全て入力してからバリデーションさせるものについて有効かと。

```sample9-2.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-2">
  <!-- .lazy修飾子 -->
  <input v-model.lazy="message">
  <p>表示：{{ message }}</p>
</div>
```
```app9-2.js
var vm = new Vue({
  el: '#app-9-2',
  data: {
    message: '',
  }
})
```
*結果*
![aaa13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/c39922d8-2910-46d1-9c77-64db8bd97b4b.gif)

#### .number修飾子

* `input`の種別が`number`だったとしても、入力内容が更新されるとStringとして判断されてしまう。
* `.number`修飾子をつけると、この問題を解決してくれるので、数値入力のinputには`.number`修飾子をつけるのがベター。

```sample9-3.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-3">
  <!-- number修飾子つけないと、変更時にStringに・・・ -->
  num1：<input 
    type="number"
    v-model="num1"
  >
  <p>num1：（表示）{{  num1 }}</p>
  <p>num1：（型）{{ typeof num1 }}</p>
  
  <hr>
  <!-- number修飾子つけると、numberのまま -->
  num2：<input 
    type="number"
    v-model.number="num2"
  >
  <p>num2：（表示）{{  num2 }}</p>
  <p>num2：（型）{{ typeof num2 }}</p>
</div>
```

```sample9-3.js
var vm = new Vue({
  el: '#app-9-3',
  data: {
    num1: 0,
    num2: 0
  }
})
```

*結果*
![aaa14.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/407ed1b1-a07d-09fc-5db3-9b4da4dc45f0.gif)


#### .trim修飾子

* 前後の空白をtrimしてくれる

```sample9-4.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-9-4">
  trimなし：<input 
    type="string"
    v-model="msg1"
  >
  <pre>{{ msg1 }}</pre>
  <hr>
  trimあり：<input 
    type="string"
    v-model.trim="msg2"
  >
  <pre>{{ msg2 }}</pre>
</div>
```

```sample9-4.js
var vm = new Vue({
  el: '#app-9-4',
  data: {
    msg1: '初期文字列',
    msg2: '初期文字列'
  }
})
```

*結果*
![aaa15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/05ddcefc-d999-9e16-ec6b-c68450235b9a.gif)



### v-if / v-else / v-else-if
* if文用のディレクティブ。他の言語と同様、if, else,else-if がある。
* **条件付きレンダリングの一つ**
* 使う頻度は・・・もちろん高いが、複雑になりすぎないように元々の設計が大事そう。
* 省略系→なし

**ルール**
v-if,v-else,v-else-ifはセットで使うようにと、以下のルールがある。
> v-else 要素は、v-if または v-else-if 要素の直後になければなりません。それ以外の場合は認識されません。
v-else と同様に、v-else-if 要素は v-if 要素またはv-else-if 要素の直後になければなりません。

*サンプルコード：単純な例*

```sample10.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-10">
  <input v-model="message">
  <button @click="change()">クリックすると文字が変わるかもしれません。</button>
  <p v-if="changeStr==='1'">
    1が押下されました
  </p>
  <p v-else-if="changeStr==='2'">
    2が押下されました
  </p>
  <p v-else-if="changeStr==='3'">
    3が押下されました
  </p>
  <p v-else>
    1~3の間の数字を押してください。
  </p>
</div>
```
```sample10.js
var vm = new Vue({
  el: '#app-10',
  data: {
    message: '',
    changeStr: ''
  },
  methods:{
    change: function() {
      this.changeStr = this.message
    }
  }
})
```

*結果*
![aaa9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/7978f095-9103-9916-c249-6b392286201b.gif)


templateを使ってグループ化もできます。以下、例。

```sample10-1.html
<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>
```

### v-show
* **条件付きレンダリングの一つ**
* `v-if`と同じように使えるが、else的なディレクティブは存在しない。
* 省略系→なし

```v-show.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-10">
  <input v-model="message">
  <button @click="change()">クリックすると文字が変わるかもしれません。</button>
  <p v-show="changeStr==='1'">
    1が押下されました
  </p>
  <p v-show="changeStr==='2'">
    2が押下されました
  </p>
  <p v-show="changeStr==='3'">
    3が押下されました
  </p>
</div>
```


### v-for（その１：基本）
* for文用のディレクティブ。
* **リストレンダリング**と呼ばれる、配列を扱うディレクティブの一つ。
* 配列でもオブジェクト（kotlinでいうとMap）でもOK。
  * 配列の場合、２つめの引数がindex（任意）
  * オブジェクトの場合、2つめの引数がオブジェクトのキー（任意）、3つめの引数がindex（任意）
* 使う頻度はもち高い。
* **【超重要】必ずkey属性を指定する**。
  * とにかくkeyを指定する笑。理由は [こちら（キーつき v-for）](https://jp.vuejs.org/v2/style-guide/#%E3%82%AD%E3%83%BC%E4%BB%98%E3%81%8D-v-for-%E5%BF%85%E9%A0%88)を参照してください。
* 省略系→なし

*サンプルコード：いろいろな書き方*

```sample-11.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-11">
  <p>example-1：オブジェクトのみ</p>
  <ul id="example-1">
    <!-- 書き方は様々 -->
    <!-- keyを忘れない-->
    <li v-for="item in items" :key="item.message">
      {{ item.message }}
    </li>
  </ul>
  
  <hr>
  <p>example-2：インデックスも。</p>
  <ul id="example-2">
    <!-- インデックスを使える -->
    <!-- keyを忘れない-->
    <li v-for="(item, index) in items"  :key="item.message">
      {{ item.message }}：インデックス→{{ index }}
    </li>
  </ul>
  
  <hr>
  <p>example-3：オブジェクトにて</p>
  <ul id="example-3">
    <!-- マップもOK -->
    <!-- keyを忘れない-->
    <li v-for="(value, key, index) of object" :key="value">
    {{ index }}. {{ key }}: {{ value }}
    </li>
  </ul>
</div>
```

```sample-11.js
var vm = new Vue({
  el: '#app-11',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ],
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})
```

*結果*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69626/a1df8ad3-a127-55f1-3f44-37d7536bceb1.png)

### v-for（その2：その他）

templateタグも使える＆回数指定のループも大丈夫。

```sample10-1.html
<!-- template -->
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

<!-- 回数指定 -->
<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

```


### 番外編：`v-show`と`v-if`のどちらを使うか？

* `v-if`
  * DOM自体を生成・破棄される。
  * template使える。
  * DOM自体を作成しないパターンがあるため、初期描画は早い。
  * コンポーネントの表示・非表示の切り替えの場合は、DOMの生成・破棄を実行するため、遅い。
* `v-show`
  * `display none`を指定して、画面に表示されないようになる。
  * templateは使えない。
  * DOM自体は作ってしまうため、初期描画が遅い。
  * コンポーネントの表示・非表示の切り替えの場合は、`display none`を切り替えするだけなので早い。
* **頻繁に表示・非表示を切り替える場合は、`v-show`を使う。それ以外の場合は、`v-if`を使う**


### 番外編：`v-for`と`v-if`の同時使用は禁止

> v-if と v-for を同時に利用することは 推奨されません。 詳細については [スタイルガイド](https://jp.vuejs.org/v2/style-guide/#v-for-%E3%81%A8%E4%B8%80%E7%B7%92%E3%81%AB-v-if-%E3%82%92%E4%BD%BF%E3%81%86%E3%81%AE%E3%82%92%E9%81%BF%E3%81%91%E3%82%8B-%E5%BF%85%E9%A0%88) を参照ください。
v-if といっしょに使用されるとき、v-for は v-if より優先度が高くなります。詳細については [リストレンダリング](https://jp.vuejs.org/v2/guide/list.html#v-for-%E3%81%A8-v-if) のガイドを参照してください。

とのこと。

### v-slot

* Vueコンポーネントのデータ受け渡しで使う
* [詳しくはこちら](https://qiita.com/sh-watanabe/private/f31473b60585ef5f30cc#%E5%BF%9C%E7%94%A8slot)