Vue.jsでタブメニューをつくる

## Vue.jsでタブメニューをつくります。

使い慣れているjQueryなら5分もかからずにデザインも込みで完了しますが、
まだ良くわかっていないVue.jsでは、正直どこから手を付けていいものやらだった。

他の記事にも書いたけど、間を開けずに取り組むべき・・・

自分の理解を深めるためにも、jQueryと改めて見比べてみました。

サンプルコードを試す場合は、jQueryもVue.jsもCDNを読み込んでください。
（このバージョンでなくてもどこのCDNでも問題ないです。）

```html
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
```

CSSの説明は割愛します。まとめてこちらです。

```css
  ul{
    margin: 0;
    padding: 0;
  }
  li{
    list-style: none;
  }
  .tabs {
    overflow: hidden;
  }
  .tabs li,
  .tabs label {
    float: left;
    padding: 10px 20px;
    border: 1px solid #ccc;
    cursor: pointer;
    transition: .3s;
  }
  .tabs li:not(:first-child),
  .tabs label:not(:first-of-type) {
    border-left: none;
  }
  .tabs li.active,
  .tabs :checked + label {
    background-color: #000;
    border-color: #000;
    color: #fff;
    cursor: auto;
  }
  .contents{
    overflow: hidden;
    margin-top: -1px;
  }
  .contents li {
    width: 320px;
    padding: 20px;
    border: 1px solid #ccc;
  }

  .jquery .contents li{
    display: none;
  }
  .jquery .contents li.active {
    display: block;
  }

  .vue_radio input{
    display: none;
  }
```

見た目はこんな感じになります。
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/34634/84b102b4-e276-d863-47bb-5f493b4dc830.png)
このあと3つの実装方法を紹介しますが、すべてこの見た目で同じ動きになります。

## jQueryで実装

タブメニューの実装方法は細かくいろいろあると思いますが、私がいつも使っている書き方を紹介します。
簡単に説明すると、タブをクリックしたら同じ番目のコンテンツを表示するというやり方です。
表示/非表示はclassをつけたりとったりで制御します。

```html
  <div class="jquery">
    <ul class="tabs">
      <li class="active">タブ1</li>
      <li>タブ2</li>
      <li>タブ3</li>
    </ul>

    <ul class="contents">
      <li class="active">コンテンツ1コンテンツ1コンテンツ1コンテンツ1</li>
      <li>コンテンツ2コンテンツ2コンテンツ2コンテンツ2</li>
      <li>コンテンツ3コンテンツ3コンテンツ3コンテンツ3</li>
    </ul>
  </div>
```

```js
$(function() {

  $('.jquery .tabs li').click(function() {
    var index = $('.jquery .tabs li').index(this);
    $('.jquery .tabs li').removeClass('active');
    $(this).addClass('active');
    $('.jquery .contents li').removeClass('active').eq(index).addClass('active');
  });
  
});
```

## Vue.jsで実装

上記のjQueryと同様の仕様のタブメニューをVue.jsで書きます。

いろいろさまよいましたが、おそらくこれが割とシンプルなやりかたなのかなと・・・
利便性を考えると、もっといろいろ書き方あると思いますが、とりあえず初心者の私にはこれが理解しやすい形です。

※1点だけ注意
HTMLとVue.jsの記述は、Vue.jsがあとで読む込まれるように書くこと。

```html
  <div id="app">

    <div class="vue">
      <ul class="tabs">
        <li v-on:click="change('1')" v-bind:class="{'active': isActive === '1'}">タブ1</li>
        <li v-on:click="change('2')" v-bind:class="{'active': isActive === '2'}">タブ2</li>
        <li v-on:click="change('3')" v-bind:class="{'active': isActive === '3'}">タブ3</li>
      </ul>

      <ul class="contents">
        <li v-if="isActive === '1'">コンテンツ1コンテンツ1コンテンツ1コンテンツ1</li>
        <li v-else-if="isActive === '2'">コンテンツ2コンテンツ2コンテンツ2コンテンツ2</li>
        <li v-else-if="isActive === '3'">コンテンツ3コンテンツ3コンテンツ3コンテンツ3</li>
      </ul>
    </div>

  </div>
```

```js
new Vue({
  el: '#app',
  data: {
    isActive: '1'
  },
  methods: {
    change: function(num){
      this.isActive = num
    }
  }
})
```

少しだけ解説をすると、`isActive`というデータを定義し、その値によってタブメニューのアクティブを制御しています。
`v-on:click="change('1')"`で、クリックしたタブの値を渡します。
`change`というメソッドで受け取った値を、`isActive`の値に更新します。
`v-if="isActive === '1'"`や`v-else-if="isActive === '2'"`で、`isActive`の値が一致していれば表示します。
以上がタブメニューの切り替えです。

アクティブになっているタブは、わかるようにスタイルを変更したいのでclassを付けたい。
`v-bind:class="{'active': isActive === '1'}"`で、`isActive === '1'`であれば`active`というクラスをつけるという指示をする。
これで、jQueryでやっていることと同じことができる。

理解するには少し時間がかかるかもしれないが、慣れてしまえばこっちのほうがいろいろやりやすそう。


## Vue.jsでラジオボタンを使って実装

ここでふと、タブメニューのアクティブとアクティブのタブにclassをつけるという2つの動作をするなら、ひとつにまとめてしまったほうが楽じゃない？と思い、ラジオボタンでもタブメニューが実装できるのではないかと模索した。

こちらも遠回りして、え、コード増えるじゃんと一回なりましたが、改めてちゃんとみてみると無駄なコードがあるある。。
そしたらめっちゃシンプルになりました。

```html
  <div id="radio">

    <div class="vue_radio">
      <div class="tabs">
        <input type="radio" id="tab1" name="tab" value="1" v-model="isActive">
        <label for="tab1">タブ1</label>
        <input type="radio" id="tab2" name="tab" value="2" v-model="isActive">
        <label for="tab2">タブ2</label>
        <input type="radio" id="tab3" name="tab" value="3" v-model="isActive">
        <label for="tab3">タブ3</label>
      </div>

      <ul class="contents">
        <li v-if="isActive === '1'">コンテンツ1コンテンツ1コンテンツ1コンテンツ1</li>
        <li v-else-if="isActive === '2'">コンテンツ2コンテンツ2コンテンツ2コンテンツ2</li>
        <li v-else-if="isActive === '3'">コンテンツ3コンテンツ3コンテンツ3コンテンツ3</li>
      </ul>
    </div>

  </div>
```

```js
new Vue({
  el: '#radio',
  data: {
    isActive: '1'
  }
})
```

`v-model`とても便利ですね！
こちらも少し解説しますと、`v-model`はvalueの値を瞬時にデータに反映します。
なので、clickの時にやった、値を受け取って更新するという記述を省略できます。
（前述したコードが増えたのは、この機能に気が付かなかったからです。）
また、ラジオボタンの`:checked`を使えば、アクティブのタブにclassをつける必要もなくなります。

よって、Vue.jsでコード1行追加のみ。
HTML側も最低限の記述だけすればすぐに実行される。


## まとめ

**Vue.js楽！！**

コードの量は明らかに少なくなり、シンプルに感じます。
また、タブを切り替えた時にアニメーションをつけたりする場合は、Vue.jsのほうが簡単に追加できるのでいいと思います。
コンポーネントを使えばもっといろいろやりやすくなりそう。

ちゃんと勉強しよ。