LoginSignup
4
8

More than 3 years have passed since last update.

【Vue.js】Vue CLI でタブ機能を作る(動的コンポーネント)

Last updated at Posted at 2020-07-23

はじめに

Vue.js を学習していて、動的コンポーネント(:is="")を活用して、タブ機能を作成してみました。
(Vue CLI を使用)

こういうやつ↓↓
スクリーンショット 2020-07-22 18.50.04.png

Vue CLI ディレクトリ構造

スクリーンショット 2020-07-22 18.49.48.png

主要ファイルの記述

以下に主要ファイルのコードを記載する

  • index.html
  • main.js
  • Tab1.vue
  • Tab2.vue
  • Tab3.vue
  • App.vue
index.html
<!DOCTYPE html>
<html lang="en">
  <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">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>Vue.js タブ</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
  </body>
</html>
main.js
import Vue from 'vue';
import App from './App.vue';

new Vue({
  render: h => h(App), // render関数にてApp.vueをレンダリング
}).$mount('#app') // index.htmlのid=appをマウント

App.vueの子コンポーネントファイルを3つ用意

Tab1.vue
<template>
  <div>
    <p>タブ1だよ</p>
  </div>
</template>
Tab2.vue
<template>
  <div>
    <p>タブ2だよ</p>
  </div>
</template>
Tab3.vue
<template>
  <div>
    <p>タブ3だよ</p>
  </div>
</template>

上記3つの子コンポーネントの親コンポーネントファイルが App.vue

App.vue
<template>
  <div>
    <ul class="tabs-menu">
      <li
        :class="{ active: currentTab === 'Tab1' }"
        @click="currentTab = 'Tab1'"
      >タブ1</li>
      <li
        :class="{ active: currentTab === 'Tab2' }"
        @click="currentTab = 'Tab2'"
      >タブ2</li>
      <li
        :class="{ active: currentTab === 'Tab3' }"
        @click="currentTab = 'Tab3'"
      >タブ3</li>
    </ul>
    <div class="tabs-content">
      <component :is="currentTab"></component>
    </div>
  </div>
</template>

<script>
import Tab1 from "./components/Tab1.vue";
import Tab2 from "./components/Tab2.vue";
import Tab3 from "./components/Tab3.vue";

export default {
  data() {
    return {
      currentTab: 'Tab1',
    };
  },
  components: {
    Tab1,
    Tab2,
    Tab3,
  }
}
</script>

<style scoped>
body {
  color: #3f4548;
}

/* ulのデフォルトスタイルを消去 */
.tabs-menu {
  margin: 0;
  padding: 0;
  list-style-type: none;
}

/* タブの基本スタイル */
.tabs-menu li {
  display: block;
  float: left;
  margin-right: 8px;
  margin-bottom: -1px;
  padding: 10px 20px;
  border-style: solid;
  border-width: 1px;
  border-color: transparent;
  border-radius: 4px 4px 0 0;
  color: #557f95;
  text-decoration: none;
}

/* タブにマウスを乗せたらカーソルの形を変える */
.tabs-menu li:hover {
  cursor: pointer;
}

/* 非選択のタブにマウスを乗せたら色を変える */
.tabs-menu li:not(.active):hover {
  border-color: #f0f0f0 #f0f0f0 #999;
  background-color: #f0f0f0;
}

/* 選択中のタブ */
.tabs-menu .active {
  border-color: #999 #999 transparent #999;
  background-color: #f0fbff;
  color: black;
}

/* タブコンテンツ表示エリア */
.tabs-content {
  clear: both;
  background-color: #f0fbff;
  border: 1px solid #999;
  border-radius: 0 4px 4px 4px;
  padding: 10px 10px 30px 10px;
}
</style>

以下で App.vue について解説↓↓

App.vue について解説

子コンポーネントファイルを読み込み

App.vue
<!-- 一部抜粋 -->
<script>
import Tab1 from "./components/Tab1.vue";
import Tab2 from "./components/Tab2.vue";
import Tab3 from "./components/Tab3.vue";

// 省略

</script>

コンポーネントをローカル登録

App.vue
<!-- 一部抜粋 -->
<script>
  components: {
    Tab1,
    Tab2,
    Tab3,
  }
}
</script>

表示タブの初期値はTab1に設定

App.vue
<!-- 一部抜粋 -->
<script>
export default {
  data() {
    return {
      currentTab: 'Tab1',
    };
  },
}
</script>

@click="currentTab = 'TabX'"でタブをクリックすると currentTab の値にコンポーネント名を代入する。

そして、<component :is="currentTab"></component>currentTab に代入されている値によって表示するコンポーネントを判別させている。

:class="{ active: currentTab === 'Tab1' }"
currentTabTab1であればactiveクラスを付与している。

App.vue
<template>
  <div>
    <ul class="tabs-menu">
      <li
        :class="{ active: currentTab === 'Tab1' }"
        @click="currentTab = 'Tab1'"
      >タブ1</li>
      <li
        :class="{ active: currentTab === 'Tab2' }"
        @click="currentTab = 'Tab2'"
      >タブ2</li>
      <li
        :class="{ active: currentTab === 'Tab3' }"
        @click="currentTab = 'Tab3'"
      >タブ3</li>
    </ul>
    <div class="tabs-content">
      <component :is="currentTab"></component> <!-- ここで表示するコンポーネントを動的に切り替えている -->    
    </div>
  </div>
</template>

最後に

<component :is="コンポーネント名"></component>を使えば、v-if v-showを使わずに簡単に動的にコンポーネントの切り替えができた。

ご指摘などありましたら、お気軽にお願いします。

●参考リファレンス
Vue.js 動的 & 非動的コンポーネント

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8