Vue.jsのv-if、v-showの違いについて

# この記事を書こうと思ったきっかけ
先月Vue.jsを使いWebアプリケーションを使う機会があったのですが
オブジェクトのデータを表示するかしないかの判定をv-ifとv-showのどちらを使用してやるかを悩みながら実装していたのですが
実装していく中で違いが明確にわかるパターンのコードを見つけたので議事録的な意味を含めて記事にまとめておこうと思います

# ベースにするコード
####HelloWorld.vue
```
<template>
  <div class="hello">
    <div v-for="box in boxs" :key="box.name" :style="[setSize(box)]">
      {{ box.name }}
    </div>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      boxs: [
        {name: 'box1', width: 100, height: 50, color: 'red'},
        {name: 'box2', width: 100, height: 100, color: 'blue'},
        {name: 'box3', width: 100, height: 150, color: 'green'}
      ]
    }
  },
  methods: {
    setSize (box) {
      console.log('methods in')
      const height = box.width + box.height
      return {
        width: box.width + '%',
        height: height + 'px',
        backgroundColor: box.color
      }
    }
  }
}
</script>
```

boxsのオブジェクトを配置し、設定しているnameの表示
styleはheightのみ定義してあるwidthとheightを足した物を設定してある
また、メソッド内に入る事を確認するために`console.log`でログを出力している
表示される画面は以下の通り
<img width="889" alt="MailPicture-10.png" src="https://qiita-image-store.s3.amazonaws.com/0/187684/dd449a92-2188-1d35-9fed-99c8c52a57ff.png">
####ログ
3つのboxがあるので`3回ログが表示される`
<img width="511" alt="MailPicture-12.png" src="https://qiita-image-store.s3.amazonaws.com/0/187684/f952a436-6c72-b537-de32-c73f91e4dea4.png">


ここでboxsのstyle要素を消していき、表示、htmlがどう表示されていくのかを確認していく

#v-ifを利用した場合
v-ifでbox内のheightがある場合だけ表示するように変更し、box2のheightを消して見る

```
<template>
  <div class="hello">
    <div v-for="box in boxs" :key="box.name" :style="[setSize(box)]" v-if="box.height">
      {{ box.name }}
    </div>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      boxs: [
        {name: 'box1', width: 100, height: 50, color: 'red'},
        {name: 'box2', width: 100, color: 'blue'},
        {name: 'box3', width: 100, height: 150, color: 'green'}
      ]
    }
  },
  methods: {
    setSize (box) {
      console.log('methods in')
      const height = box.width + box.height
      return {
        width: box.width + '%',
        height: height + 'px',
        backgroundColor: box.color
      }
    }
  }
}
</script>
```
###結果
box2の要素が<!---->に置きかわり表示されなくなる事がわかった
<img width="884" alt="MailPicture-11.png" src="https://qiita-image-store.s3.amazonaws.com/0/187684/57899f84-073b-1288-2471-f9d9879d8ee3.png">

####ログ
boxの要素が消えた事からsetSizeには`2回しか入らない`事がわかった
<img width="490" alt="MailPicture-13.png" src="https://qiita-image-store.s3.amazonaws.com/0/187684/45f2bf1d-c36e-c3a6-75c1-55f3360c32d8.png">


#v-showを利用した場合
先ほどv-ifで書いた場所をv-showに変更するのみ

```
<template>
  <div class="hello">
    <div v-for="box in boxs" :key="box.name" :style="[setSize(box)]" v-show="box.height">
      {{ box.name }}
    </div>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      boxs: [
        {name: 'box1', width: 100, height: 50, color: 'red'},
        {name: 'box2', width: 100, color: 'blue'},
        {name: 'box3', width: 100, height: 150, color: 'green'}
      ]
    }
  },
  methods: {
    setSize (box) {
      console.log('methods in')
      const height = box.width + box.height
      return {
        width: box.width + '%',
        height: height + 'px',
        backgroundColor: box.color
      }
    }
  }
}
</script>
```
###結果
box2には`display:none`のstyleが付き、html上は残っているがstyleで表示されなくなる事がわかった

####ログ
box2の情報は残ったままになっているため`3回ログ出力される`事がわかった
<img width="495" alt="MailPicture-15.png" src="https://qiita-image-store.s3.amazonaws.com/0/187684/7835764c-4d78-33fa-9733-b010e705f82b.png">

#まとめ
v-ifとv-showを実際に同じコードで使用してみた場合以下のようになることが分かった

|  | html上の表示 | 関数を通るか？ |
|:-:|:-:|:-:|
| v-if |  非表示(オブジェクトremove) | 通らない |
| v-show | 非表示(display:none) | 通る |

画面上では表示されないのは双方変わらないが、オブジェクトがv-forで繰り返しを行う中で関数を利用している場合はv-showを使っていると意図せずに関数の中に入ってしまうことがあるので注意が必要ということがわかった

#最後に
自分はサイズが必須なところでv-showを使っていてデータを入力中の中途半端な状態になった際に
関数内で計算を行おうとして画面が真っ白になってしまう失敗をしてしまった

今回は自分の議事録としてだがv-if、v-showの使い分けに悩んでいる助けになればと思います（人）