【Vue.js】動的に行が増減する<table>でもゼブラ柄を効かせたい！

&lt;table&gt;を使ってデータを見せる際に可視性を上げるために使いがちなゼブラ柄（ストライプ？）。見やすくて使いやすいですよね！

↓こういうやつ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95865/078bc57f-d565-5444-3b59-7a0c140542b9.png)
みんな大好きBootstrapでも「.table-striped」というclassがこんな風になってるわけですが、とにかく使い勝手が良いものです。

```css
.table-striped tbody tr:nth-of-type(odd) {
    background-color: rgba(0, 0, 0, .05);
}
```

# やってみる
では作ってみましょう。&lt;tr&gt;を何行も書きたくないのでVue.jsで書きます。
世界最大級の動物を重さで順位付けした10位までを&lt;table&gt;表示できました。見事なゼブラ柄です！気分が良い！

<p class="codepen" data-height="400" data-theme-id="0" data-default-tab="result" data-user="ryo_hisano" data-slug-hash="ZYVwag" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ZYVwag">
  <span>See the Pen <a href="https://codepen.io/ryo_hisano/pen/ZYVwag/">
  ZYVwag</a> by ryo_hisano (<a href="https://codepen.io/ryo_hisano">@ryo_hisano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 表示・非表示したい
TODOアプリのように、チェック入れた行を消したい気分になったので、適当なclassを作り、選択されたものを非表示にしようと考えました。

```css
.hidden {
    display: none;
}
```

```html
<tr v-for="data in datas" :key="data.id" v-bind:class='{hidden:data.hide}'>
```

<p class="codepen" data-height="400" data-theme-id="0" data-default-tab="result" data-user="ryo_hisano" data-slug-hash="qzKRbg" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="qzKRbg">
  <span>See the Pen <a href="https://codepen.io/ryo_hisano/pen/qzKRbg/">
  qzKRbg</a> by ryo_hisano (<a href="https://codepen.io/ryo_hisano">@ryo_hisano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

出来た！と思ってチェック入れていくと…ぎゃーす！全然美しくなくなった！なんでや・・・
↓複数チェック入れたとき↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95865/117bf140-9831-28a0-669d-f9aa5b3707bc.png)

一旦落ちついて考えましょう。MDNによると下記のようにあります。
> CSS の :nth-of-type() 疑似クラスは、兄弟要素のグループの中で指定された型の要素を、位置に基づいて選択します
[:nth-of-type() - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/:nth-of-type)

CSSで見栄え上非表示にした所で、HTML構造に変わりは無いため、このようになります。当たり前っちゃ当たり前です。先程のキャプチャで行くと、こう。

```
1.グレー
2.白（非表示）
3.グレー
4.白（非表示）
5.グレー
6.白
```

# どうするか？（悪手）

&lt;tr&gt;タグを別のタグで囲ってしまえばどうでしょう。囲われた&lt;tr&gt;タグは兄弟要素では無くなるはずなので、スキップした状態でゼブラ柄が適用されるのでは？

```html
<tr>...</tr>
<hidden class="hidden">
    <tr>...</tr>
</hidden>
<tr>...</tr>
```

適当に&lt;tr&gt;にidを振り、それを基に&lt;hidden class="hidden"&gt;で囲ったり解除したりするような関数を作ってやります（jQueryで言う所のwrap / unwrap的な）。

どうやらうまく行ったようです。

<p class="codepen" data-height="400" data-theme-id="0" data-default-tab="result" data-user="ryo_hisano" data-slug-hash="xozgVQ" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="xozgVQ">
  <span>See the Pen <a href="https://codepen.io/ryo_hisano/pen/xozgVQ/">
  xozgVQ</a> by ryo_hisano (<a href="https://codepen.io/ryo_hisano">@ryo_hisano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# とは言うものの…
独自タグで囲むなどと、すこぶる気持ち悪いです！
そういえばVue.jsを使っていたのでした！奇遇ですね！

```html
<tr v-for="data in visibleData" :key="data.id">
```

```javascript
computed: {
    visibleData() {
        return this.datas.filter(function(data) {
            return !data.hide;
        });
    }
}
```

Vue.jsなら行の削除も復元もお手軽です。

<p class="codepen" data-height="400" data-theme-id="0" data-default-tab="result" data-user="ryo_hisano" data-slug-hash="JQZEKw" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="JQZEKw">
  <span>See the Pen <a href="https://codepen.io/ryo_hisano/pen/JQZEKw/">
  JQZEKw</a> by ryo_hisano (<a href="https://codepen.io/ryo_hisano">@ryo_hisano</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#まとめ
Vue.js以外のケースでも、行の削除と行の復活が出来るように作れれば、動的に行が増減する&lt;table&gt;でも問題なくゼブラ柄を使うことが可能ですね！

#参考
[スタイルガイド — Vue.js](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)