【Vue】 v-forの基本的な使い方 + v-forにおけるkeyの目的 

## 概要
v-forを **配列**、**オブジェクト**、**数値**に使用する方法と、
v-forには**key属性**をなるべくつけようということを説明する記事です。

## 0. はじめに

下記のhtmlファイルにプログラムする前提で説明する。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://unpkg.com/vue@next"></script>
  <title>Document</title>
</head>
<body>
  <div id="app">
    <!-- htmlはここに書く ----------------->
  </div>
  
  <script>
    // ** jsはここに書く *******************
  </script>
</body>
</html>
```

## 1. 配列にv-forを使用する

```vue
  <div id="app">
    <div v-for="item in items">
      {{item}}
    </div>
  </div>
```

```js
    const App = {
      data() {
        return {
          items:[123,456,789]
        }
      },
    }
    Vue.createApp(App).mount('#app')
```

![image-20210517185717846.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/6e08f088-e909-d96f-2c47-ed283fabc20d.png)


一般的なfor文とVueのv-forディレクティブを対応させた場合、下記になる。

* js : `for(let i = 0; i < array.length; i++)`

* Vue : `v-for='i in array'`



また、配列の場合、**第二引数に配列のindex**をとることができる。

```vue
  <div id="app">
    <div v-for="(item, index) in items">
      {{index}} : {{item}}
    </div>
  </div>
```

![image-20210517185842540.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/658429d2-2ac2-5be0-2a4b-eab89c8cbd5c.png)

## 2. オブジェクトにv-forを使用する

オブジェクトの場合も配列と同じように制御できる。違いは、**引数を3つ (value, key, index)** まで取ることができる点。

```vue
  <div id="app">
  <!-- 値だけ使用する場合は, <div v-for="value in object"> でよい -->
    <div v-for="(value, key, index) in object">
      {{index}}. {{key}} : {{value}}
    </div>
  </div>
```

```js
    const App = {
      data() {
        return {
          object: {
            name: 'moumou',
            age: '12',
            title: 'vue'
          }
        }
      },
    }
    
    Vue.createApp(App).mount('#app')
```

![image-20210517191201811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/a8d8d37c-5114-bbfe-0bca-d2edf0d17fd4.png)




## 3. 数値にv-forを使用する

`v-for="i in 3"`のように、配列やオブジェクト以外にも数値を指定できる。

```html
  <div id="app">
    <div v-for="i in 3">
      {{i}}
    </div>
  </div>
```

![image-20210517191432344.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/3f50a1d7-c40a-f39b-f787-52fcbba18848.png)


## 4. key属性はなるべくつけよう

今までのv-forにはkey属性をつけていなかったが、つけないと以下のような問題が発生する。

```html
  <div id="app">
    <button @click="array.shift()">delete</button>
    <div v-for="english in array">
      {{english}} 
      <input type="text">
    </div>
  </div>
```

```js
    const App = {
      data() {
        return {
          array: ['first', 'second', 'third']
        }
      },
    }
    
    Vue.createApp(App).mount('#app')
```

このプログラムはdeleteを押下すると、shift()を使用して`array`の配列の先頭が削除する。
![image-20210517192651979.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/bba599cf-df32-a204-c7fa-078281d628ea.png)
deleteを押下すると、
![image-20210517192804204.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/39e8c289-6429-4aff-a44e-1e6fb3c62f7c.png)
`second`の隣のインプットの値が`second`ではなく`first`になってしまう。これは[Vueの特性](https://v3.ja.vuejs.org/guide/list.html#%E7%8A%B6%E6%85%8B%E3%81%AE%E7%B6%AD%E6%8C%81)で、なるべく効率の良い形で描画するために生じる問題である。これを解決するためには、**key属性**を付与すればよい。
![image-20210517193446085.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/cfc32937-dc2c-d266-bfd0-35de221105bf.png)

```html
  <div id="app">
    <button @click="array.shift()">delete</button>
    <div v-for="(english, i) in array" :key="english">
      {{english}} 
      <input type="text">
    </div>
  </div>
```

上のプログラムは、**v-bind(:) を使用して配列の値をkeyにバインディング**した例。
注意点として、**key属性には文字列や数値を使用**すること。こうすることで、先頭を削除してもインプットの値も状態の維持ができる。
![image-20210517194044596.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/55da427e-140f-6538-3474-0f88ee9ad973.png)

https://v3.ja.vuejs.org/guide/list.html#%E3%83%AA%E3%82%B9%E3%83%88%E3%83%AC%E3%83%B3%E3%82%BF%E3%82%99%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%99